From d5224b73ccd09a6759759791f58426b6acd4a2e2 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 26 Mar 2024 14:09:39 -0700 Subject: [PATCH 001/541] [tsan] Refine fstat{,64} interceptors (#86625) In glibc versions before 2.33. `libc_nonshared.a` defines `__fxstat/__fxstat64` but there is no `fstat/fstat64`. glibc 2.33 added `fstat/fstat64` and obsoleted `__fxstat/__fxstat64`. Ports added after 2.33 do not provide `__fxstat/__fxstat64`, so our `fstat/fstat64` interceptors using `__fxstat/__fxstat64` interceptors would lead to runtime failures on such ports (LoongArch and certain RISC-V ports). Similar to https://reviews.llvm.org/D118423, refine the conditions that we define fstat{,64} interceptors. `fstat` is supported by musl/*BSD while `fstat64` is glibc only. --- .../lib/tsan/rtl/tsan_interceptors_posix.cpp | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 3103f4717c16..94adea777caf 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -14,6 +14,7 @@ #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_errno.h" +#include "sanitizer_common/sanitizer_glibc_version.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" @@ -1613,47 +1614,40 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { FdAccess(thr, pc, fd); return REAL(__fxstat)(version, fd, buf); } -#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat) + +TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { + SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); + if (fd > 0) + FdAccess(thr, pc, fd); + return REAL(__fxstat64)(version, fd, buf); +} +#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat); TSAN_INTERCEPT(__fxstat64) #else #define TSAN_MAYBE_INTERCEPT___FXSTAT #endif +#if !SANITIZER_GLIBC || __GLIBC_PREREQ(2, 33) TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_GLIBC - SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf); - if (fd > 0) - FdAccess(thr, pc, fd); - return REAL(__fxstat)(0, fd, buf); -#else SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); return REAL(fstat)(fd, buf); -#endif -} - -#if SANITIZER_GLIBC -TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { - SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); - if (fd > 0) - FdAccess(thr, pc, fd); - return REAL(__fxstat64)(version, fd, buf); } -#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64) +# define TSAN_MAYBE_INTERCEPT_FSTAT TSAN_INTERCEPT(fstat) #else -#define TSAN_MAYBE_INTERCEPT___FXSTAT64 +# define TSAN_MAYBE_INTERCEPT_FSTAT #endif -#if SANITIZER_GLIBC +#if __GLIBC_PREREQ(2, 33) TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { - SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); + SCOPED_TSAN_INTERCEPTOR(fstat64, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); - return REAL(__fxstat64)(0, fd, buf); + return REAL(fstat64)(fd, buf); } -#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64) +# define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64) #else -#define TSAN_MAYBE_INTERCEPT_FSTAT64 +# define TSAN_MAYBE_INTERCEPT_FSTAT64 #endif TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) { @@ -2985,10 +2979,9 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pthread_once); - TSAN_INTERCEPT(fstat); TSAN_MAYBE_INTERCEPT___FXSTAT; + TSAN_MAYBE_INTERCEPT_FSTAT; TSAN_MAYBE_INTERCEPT_FSTAT64; - TSAN_MAYBE_INTERCEPT___FXSTAT64; TSAN_INTERCEPT(open); TSAN_MAYBE_INTERCEPT_OPEN64; TSAN_INTERCEPT(creat); -- GitLab From 80487e1c622d51f4c0df12b64cca8a0b346e9b85 Mon Sep 17 00:00:00 2001 From: Piotr Zegar Date: Tue, 26 Mar 2024 21:09:54 +0000 Subject: [PATCH 002/541] [clang-tidy][NFC] Reorder entrys in release notes Sort entrys in release notes. --- clang-tools-extra/docs/ReleaseNotes.rst | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 14c48547bcbe..78b09d23d442 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -180,13 +180,13 @@ Changes in existing checks ` check to properly handle return type in lambdas and in nested functions. -- Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer - ` +- Improved :doc:`cppcoreguidelines-prefer-member-initializer + ` check by removing enforcement of rule `C.48 `_, which was deprecated since :program:`clang-tidy` 17. This rule is now covered by :doc:`cppcoreguidelines-use-default-member-init - ` and fixes + `. Fixed incorrect hints when using list-initialization. - Improved :doc:`google-build-namespaces @@ -236,14 +236,19 @@ Changes in existing checks ` check to also remove any trailing whitespace when deleting the ``virtual`` keyword. +- Improved :doc:`modernize-use-using ` + check by adding support for detection of typedefs declared on function level. + - Improved :doc:`performance-unnecessary-copy-initialization ` check by detecting more cases of constant access. In particular, pointers can be analyzed, se the check now handles the common patterns `const auto e = (*vector_ptr)[i]` and `const auto e = vector_ptr->at(i);`. -- Improved :doc:`modernize-use-using ` - check by adding support for detection of typedefs declared on function level. +- Improved :doc:`readability-identifier-naming + ` check in `GetConfigPerFile` + mode by resolving symbolic links to header files. Fixed handling of Hungarian + Prefix when configured to `LowerCase`. - Improved :doc:`readability-implicit-bool-conversion ` check to provide @@ -254,11 +259,6 @@ Changes in existing checks ` check to properly emit warnings for static data member with an in-class initializer. -- Improved :doc:`readability-identifier-naming - ` check in `GetConfigPerFile` - mode by resolving symbolic links to header files. Fixed handling of Hungarian - Prefix when configured to `LowerCase`. - - Improved :doc:`readability-static-definition-in-anonymous-namespace ` check by resolving fix-it overlaps in template code by disregarding implicit @@ -273,9 +273,9 @@ Removed checks Miscellaneous ^^^^^^^^^^^^^ -- Fixed incorrect formatting in ``clang-apply-replacements`` when no ``--format`` - option is specified. Now ``clang-apply-replacements`` applies formatting only with - the option. +- Fixed incorrect formatting in :program:`clang-apply-replacements` when no + ``--format`` option is specified. Now :program:`clang-apply-replacements` + applies formatting only with the option. Improvements to include-fixer ----------------------------- -- GitLab From a22bd00ce03a77a38be2911979a4c4f2ca01379d Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Tue, 26 Mar 2024 14:18:41 -0700 Subject: [PATCH 003/541] [libc] [bazel] [NFC] Format deps. --- utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 57dc75a3a48e..e0790e0ab59e 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -622,12 +622,12 @@ libc_support_library( name = "__support_fputil_basic_operations", hdrs = ["src/__support/FPUtil/BasicOperations.h"], deps = [ - ":__support_fputil_fenv_impl", - ":__support_macros_optimization", - ":__support_uint128", ":__support_common", ":__support_cpp_type_traits", + ":__support_fputil_fenv_impl", ":__support_fputil_fp_bits", + ":__support_macros_optimization", + ":__support_uint128", ], ) -- GitLab From c6d419c15bf836085392212b8ab7600f7402829b Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 26 Mar 2024 22:27:11 +0100 Subject: [PATCH 004/541] [TOSA] Allow all integer types in most ops (#86509) As discussed in one of the previous TOSA community meetings, we would like to allow for more integer types in the TOSA dialect to enable more use cases. For strict standards conformance, the TosaValidation pass can be used. Follow up PRs will extend conversions from TOSA where needed. --- mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td | 2 +- .../mlir/Dialect/Tosa/IR/TosaTypesBase.td | 27 +++------- .../Tosa/Transforms/TosaValidation.cpp | 51 +++++++++++++++++-- mlir/test/Dialect/Tosa/level_check.mlir | 16 ++++++ 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td index 0ecded75c5d8..306e4a439520 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td @@ -1942,7 +1942,7 @@ def Tosa_ConstOp : Tosa_Op<"const", [ConstantLike, Pure, ); let results = (outs - TensorOf<[AnyTypeOf<[Tosa_AnyNumber_Plus_F64, Tosa_Int4]>]>:$output + TensorOf<[AnyTypeOf<[Tosa_AnyNumber_Plus_F64]>]>:$output ); let hasFolder = 1; diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td index 5a4d6ff464f1..cff3de0a69af 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td @@ -38,29 +38,17 @@ class Tosa_QuantizedType params, bit signed> // Used to express accumulator results or compare results. //===----------------------------------------------------------------------===// -def Tosa_UInt8 : UI<8>; -def Tosa_UInt16 : UI<16>; - def Tosa_Int4 : I<4>; def Tosa_Int8 : I<8>; -def Tosa_Int16 : I<16>; def Tosa_Int32 : I<32>; -def Tosa_Int48 : I<48>; def Tosa_Int64 : I<64>; -def Tosa_SignedInt : AnyTypeOf<[Tosa_Int8, - Tosa_Int16, - Tosa_Int32, - Tosa_Int48, - Tosa_Int64]>; - -def Tosa_Bool : I<1>; - -// No unsigned unquantized int types. -def Tosa_Int : AnyTypeOf<[Tosa_Bool, - Tosa_UInt8, - Tosa_UInt16, - Tosa_SignedInt]>; +// The TOSA dialect allows more types than the TOSA standard to allow for +// experimentation. For historical reasons, signless is used in the place of +// signed. +// The TosaValidation pass can be used to check for standard conformance. +def Tosa_Int : AnyTypeOf<[AnyUnsignedInteger, + AnySignlessInteger]>; def Tosa_Int32Or64 : AnyTypeOf<[Tosa_Int32, Tosa_Int64]>; @@ -172,9 +160,6 @@ class Tosa_TypeLike types, string description = ""> : TypeConstraint< def Tosa_IntLike : Tosa_TypeLike<[Tosa_Int], "signless-integer-like">; def Tosa_Int8Like : Tosa_TypeLike<[Tosa_Int8], "signless-integer-8-bit-like">; -def Tosa_Int16Like : Tosa_TypeLike<[Tosa_Int16], "signless-integer-16-bit-like">; -def Tosa_Int32Like : Tosa_TypeLike<[Tosa_Int32], "signless-integer-32-bit-like">; -def Tosa_Int64Like : Tosa_TypeLike<[Tosa_Int64], "signless-integer-64-bit-like">; //===----------------------------------------------------------------------===// // Attribute predicates and classes. diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp index 967775281ad9..74ef6381f3d7 100644 --- a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp +++ b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp @@ -410,6 +410,8 @@ private: bool CheckVariable(Operation *op); bool CheckVariableReadOrWrite(Operation *op); + bool isValidElementType(Type type); + SmallVector> constCheckers; TosaLevel tosaLevel; DenseMap variablesMap; @@ -503,15 +505,58 @@ LogicalResult TosaValidation::applyVariableCheck(Operation *op) { return success(); } +bool TosaValidation::isValidElementType(Type type) { + if ((profile == TosaProfileEnum::BaseInference) && isa(type)) { + return false; + } + if (type.isF64()) { + return false; + } + if (auto intTy = dyn_cast(type)) { + if (intTy.isUnsigned()) { + switch (intTy.getWidth()) { + case 8: + case 16: + return true; + default: + return false; + } + } else { + // Signless - treated as signed. + switch (intTy.getWidth()) { + case 1: + case 4: + case 8: + case 16: + case 32: + case 48: + case 64: + return true; + default: + return false; + } + } + return false; + } + return true; +} + void TosaValidation::runOnOperation() { configLevelAndProfile(); getOperation().walk([&](Operation *op) { for (Value operand : op->getOperands()) { - if ((profile == TosaProfileEnum::BaseInference) && - isa(getElementTypeOrSelf(operand))) { + auto elementTy = getElementTypeOrSelf(operand); + if (!isValidElementType(elementTy)) { + op->emitOpError() << "is not profile-aligned: element type " + << elementTy << " is not legal"; return signalPassFailure(); } - if (getElementTypeOrSelf(operand).isF64()) { + } + for (Type resultTy : op->getResultTypes()) { + auto elementTy = getElementTypeOrSelf(resultTy); + if (!isValidElementType(elementTy)) { + op->emitOpError() << "is not profile-aligned: element type " + << elementTy << " is not legal"; return signalPassFailure(); } } diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir index 35ecbcc799e3..d8dd878051f1 100644 --- a/mlir/test/Dialect/Tosa/level_check.mlir +++ b/mlir/test/Dialect/Tosa/level_check.mlir @@ -115,6 +115,22 @@ func.func @test_const(%arg0 : tensor<1x1xi32>) -> tensor<1x1x1x1x1x1x1xi32> { // ----- +func.func @test_const_i2(%arg0 : tensor<1xi2>) { + // expected-error@+1 {{'tosa.const' op is not profile-aligned: element type 'i2' is not legal}} + %0 = "tosa.const"() {value = dense<0> : tensor<1xi2>} : () -> tensor<1xi2> + return +} + +// ----- + +func.func @test_const_ui32(%arg0 : tensor<1xui32>) { + // expected-error@+1 {{'tosa.const' op is not profile-aligned: element type 'ui32' is not legal}} + %0 = "tosa.const"() {value = dense<0> : tensor<1xui32>} : () -> tensor<1xui32> + return +} + +// ----- + func.func @test_avgpool2d_kernel_y(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x32x32x8xf32> { // expected-error@+1 {{'tosa.avg_pool2d' op failed level check: kernel <= MAX_KERNEL}} %0 = "tosa.avg_pool2d"(%arg0) {kernel = array, pad = array, stride = array, acc_type = f32} : -- GitLab From 630283c38bce9ec188c96ddb90b8251afc2b3d8e Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 26 Mar 2024 16:35:32 -0500 Subject: [PATCH 005/541] [libc] Fix misplaced `[[noreturn]]` attribute. Summary: This needs to go after `extern "C"`. --- libc/src/__support/OSUtil/baremetal/quick_exit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/__support/OSUtil/baremetal/quick_exit.cpp b/libc/src/__support/OSUtil/baremetal/quick_exit.cpp index f0971d4db352..5b6fcf42341e 100644 --- a/libc/src/__support/OSUtil/baremetal/quick_exit.cpp +++ b/libc/src/__support/OSUtil/baremetal/quick_exit.cpp @@ -9,7 +9,7 @@ #include "src/__support/OSUtil/quick_exit.h" // This is intended to be provided by the vendor. -[[noreturn]] extern "C" void __llvm_libc_quick_exit(int status); +extern "C" [[noreturn]] void __llvm_libc_quick_exit(int status); namespace LIBC_NAMESPACE { -- GitLab From 1949f7d6c9bd59172c01c7933e1c558797c47eac Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Tue, 26 Mar 2024 14:47:48 -0700 Subject: [PATCH 006/541] [scudo] Clean up string handling (#86364) Do not abort if a vector cannot increase its own capacity. In that case, push_back calls silently fail. Modify the ScopedString implementation so that it no longer requires two passes to do the format. Move the helper functions to be private member functions so that they can use push_back directly. This allows the capacity to be increased under the hood and/or silently discards data if the capacity is exceeded and cannot be increased. Add new tests for the Vector and ScopedString for capacity increase failures. Doing this so that if a map call fails, and we are attempting to write an error string, we can still get some of the message dumped. This also avoids crashing in Scudo code, and makes the caller handle any failures. --- compiler-rt/lib/scudo/standalone/fuchsia.cpp | 7 +- .../lib/scudo/standalone/mem_map_fuchsia.cpp | 7 +- .../lib/scudo/standalone/report_linux.cpp | 25 ++- .../lib/scudo/standalone/string_utils.cpp | 148 +++++++----------- .../lib/scudo/standalone/string_utils.h | 13 +- .../scudo/standalone/tests/strings_test.cpp | 32 ++++ .../scudo/standalone/tests/vector_test.cpp | 35 +++++ compiler-rt/lib/scudo/standalone/vector.h | 21 ++- 8 files changed, 165 insertions(+), 123 deletions(-) diff --git a/compiler-rt/lib/scudo/standalone/fuchsia.cpp b/compiler-rt/lib/scudo/standalone/fuchsia.cpp index 0788c4198e53..2144f1b63f89 100644 --- a/compiler-rt/lib/scudo/standalone/fuchsia.cpp +++ b/compiler-rt/lib/scudo/standalone/fuchsia.cpp @@ -34,11 +34,10 @@ static_assert(ZX_HANDLE_INVALID == 0, ""); static void NORETURN dieOnError(zx_status_t Status, const char *FnName, uptr Size) { - char Error[128]; - formatString(Error, sizeof(Error), - "SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, + ScopedString Error; + Error.append("SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, Size >> 10, zx_status_get_string(Status)); - outputRaw(Error); + outputRaw(Error.data()); die(); } diff --git a/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp b/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp index 0566ab065526..28e5a11a37f2 100644 --- a/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp +++ b/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp @@ -22,11 +22,10 @@ namespace scudo { static void NORETURN dieOnError(zx_status_t Status, const char *FnName, uptr Size) { - char Error[128]; - formatString(Error, sizeof(Error), - "SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, + ScopedString Error; + Error.append("SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, Size >> 10, _zx_status_get_string(Status)); - outputRaw(Error); + outputRaw(Error.data()); die(); } diff --git a/compiler-rt/lib/scudo/standalone/report_linux.cpp b/compiler-rt/lib/scudo/standalone/report_linux.cpp index 6a983036e6cd..dfddef3324bd 100644 --- a/compiler-rt/lib/scudo/standalone/report_linux.cpp +++ b/compiler-rt/lib/scudo/standalone/report_linux.cpp @@ -24,33 +24,30 @@ namespace scudo { // Fatal internal map() error (potentially OOM related). void NORETURN reportMapError(uptr SizeIfOOM) { - char Error[128] = "Scudo ERROR: internal map failure\n"; + ScopedString Error; + Error.append("Scudo ERROR: internal map failure"); if (SizeIfOOM) { - formatString( - Error, sizeof(Error), - "Scudo ERROR: internal map failure (NO MEMORY) requesting %zuKB\n", - SizeIfOOM >> 10); + Error.append(" (NO MEMORY) requesting %zuKB", SizeIfOOM >> 10); } - reportRawError(Error); + Error.append("\n"); + reportRawError(Error.data()); } void NORETURN reportUnmapError(uptr Addr, uptr Size) { - char Error[128]; - formatString(Error, sizeof(Error), - "Scudo ERROR: internal unmap failure (error desc=%s) Addr 0x%zx " + ScopedString Error; + Error.append("Scudo ERROR: internal unmap failure (error desc=%s) Addr 0x%zx " "Size %zu\n", strerror(errno), Addr, Size); - reportRawError(Error); + reportRawError(Error.data()); } void NORETURN reportProtectError(uptr Addr, uptr Size, int Prot) { - char Error[128]; - formatString( - Error, sizeof(Error), + ScopedString Error; + Error.append( "Scudo ERROR: internal protect failure (error desc=%s) Addr 0x%zx " "Size %zu Prot %x\n", strerror(errno), Addr, Size, Prot); - reportRawError(Error); + reportRawError(Error.data()); } } // namespace scudo diff --git a/compiler-rt/lib/scudo/standalone/string_utils.cpp b/compiler-rt/lib/scudo/standalone/string_utils.cpp index d4e4e3becd0e..e584bd806e57 100644 --- a/compiler-rt/lib/scudo/standalone/string_utils.cpp +++ b/compiler-rt/lib/scudo/standalone/string_utils.cpp @@ -14,30 +14,21 @@ namespace scudo { -static int appendChar(char **Buffer, const char *BufferEnd, char C) { - if (*Buffer < BufferEnd) { - **Buffer = C; - (*Buffer)++; - } - return 1; -} - // Appends number in a given Base to buffer. If its length is less than // |MinNumberLength|, it is padded with leading zeroes or spaces, depending // on the value of |PadWithZero|. -static int appendNumber(char **Buffer, const char *BufferEnd, u64 AbsoluteValue, - u8 Base, u8 MinNumberLength, bool PadWithZero, - bool Negative, bool Upper) { +void ScopedString::appendNumber(u64 AbsoluteValue, u8 Base, u8 MinNumberLength, + bool PadWithZero, bool Negative, bool Upper) { constexpr uptr MaxLen = 30; RAW_CHECK(Base == 10 || Base == 16); RAW_CHECK(Base == 10 || !Negative); RAW_CHECK(AbsoluteValue || !Negative); RAW_CHECK(MinNumberLength < MaxLen); - int Res = 0; if (Negative && MinNumberLength) --MinNumberLength; - if (Negative && PadWithZero) - Res += appendChar(Buffer, BufferEnd, '-'); + if (Negative && PadWithZero) { + String.push_back('-'); + } uptr NumBuffer[MaxLen]; int Pos = 0; do { @@ -55,34 +46,32 @@ static int appendNumber(char **Buffer, const char *BufferEnd, u64 AbsoluteValue, Pos--; for (; Pos >= 0 && NumBuffer[Pos] == 0; Pos--) { char c = (PadWithZero || Pos == 0) ? '0' : ' '; - Res += appendChar(Buffer, BufferEnd, c); + String.push_back(c); } if (Negative && !PadWithZero) - Res += appendChar(Buffer, BufferEnd, '-'); + String.push_back('-'); for (; Pos >= 0; Pos--) { char Digit = static_cast(NumBuffer[Pos]); Digit = static_cast((Digit < 10) ? '0' + Digit : (Upper ? 'A' : 'a') + Digit - 10); - Res += appendChar(Buffer, BufferEnd, Digit); + String.push_back(Digit); } - return Res; } -static int appendUnsigned(char **Buffer, const char *BufferEnd, u64 Num, - u8 Base, u8 MinNumberLength, bool PadWithZero, - bool Upper) { - return appendNumber(Buffer, BufferEnd, Num, Base, MinNumberLength, - PadWithZero, /*Negative=*/false, Upper); +void ScopedString::appendUnsigned(u64 Num, u8 Base, u8 MinNumberLength, + bool PadWithZero, bool Upper) { + appendNumber(Num, Base, MinNumberLength, PadWithZero, /*Negative=*/false, + Upper); } -static int appendSignedDecimal(char **Buffer, const char *BufferEnd, s64 Num, - u8 MinNumberLength, bool PadWithZero) { +void ScopedString::appendSignedDecimal(s64 Num, u8 MinNumberLength, + bool PadWithZero) { const bool Negative = (Num < 0); const u64 UnsignedNum = (Num == INT64_MIN) ? static_cast(INT64_MAX) + 1 : static_cast(Negative ? -Num : Num); - return appendNumber(Buffer, BufferEnd, UnsignedNum, 10, MinNumberLength, - PadWithZero, Negative, /*Upper=*/false); + appendNumber(UnsignedNum, 10, MinNumberLength, PadWithZero, Negative, + /*Upper=*/false); } // Use the fact that explicitly requesting 0 Width (%0s) results in UB and @@ -90,44 +79,45 @@ static int appendSignedDecimal(char **Buffer, const char *BufferEnd, s64 Num, // Width == 0 - no Width requested // Width < 0 - left-justify S within and pad it to -Width chars, if necessary // Width > 0 - right-justify S, not implemented yet -static int appendString(char **Buffer, const char *BufferEnd, int Width, - int MaxChars, const char *S) { +void ScopedString::appendString(int Width, int MaxChars, const char *S) { if (!S) S = ""; - int Res = 0; + int NumChars = 0; for (; *S; S++) { - if (MaxChars >= 0 && Res >= MaxChars) + if (MaxChars >= 0 && NumChars >= MaxChars) break; - Res += appendChar(Buffer, BufferEnd, *S); + String.push_back(*S); + NumChars++; + } + if (Width < 0) { + // Only left justification supported. + Width = -Width - NumChars; + while (Width-- > 0) + String.push_back(' '); } - // Only the left justified strings are supported. - while (Width < -Res) - Res += appendChar(Buffer, BufferEnd, ' '); - return Res; } -static int appendPointer(char **Buffer, const char *BufferEnd, u64 ptr_value) { - int Res = 0; - Res += appendString(Buffer, BufferEnd, 0, -1, "0x"); - Res += appendUnsigned(Buffer, BufferEnd, ptr_value, 16, - SCUDO_POINTER_FORMAT_LENGTH, /*PadWithZero=*/true, - /*Upper=*/false); - return Res; +void ScopedString::appendPointer(u64 ptr_value) { + appendString(0, -1, "0x"); + appendUnsigned(ptr_value, 16, SCUDO_POINTER_FORMAT_LENGTH, + /*PadWithZero=*/true, + /*Upper=*/false); } -static int formatString(char *Buffer, uptr BufferLength, const char *Format, - va_list Args) { +void ScopedString::vappend(const char *Format, va_list &Args) { + // Since the string contains the '\0' terminator, put our size before it + // so that push_back calls work correctly. + DCHECK(String.size() > 0); + String.resize(String.size() - 1); + static const char *PrintfFormatsHelp = - "Supported formatString formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; " + "Supported formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; " "%[-]([0-9]*)?(\\.\\*)?s; %c\n"; RAW_CHECK(Format); - RAW_CHECK(BufferLength > 0); - const char *BufferEnd = &Buffer[BufferLength - 1]; const char *Cur = Format; - int Res = 0; for (; *Cur; Cur++) { if (*Cur != '%') { - Res += appendChar(&Buffer, BufferEnd, *Cur); + String.push_back(*Cur); continue; } Cur++; @@ -162,7 +152,7 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, DVal = HaveLL ? va_arg(Args, s64) : HaveZ ? va_arg(Args, sptr) : va_arg(Args, int); - Res += appendSignedDecimal(&Buffer, BufferEnd, DVal, Width, PadWithZero); + appendSignedDecimal(DVal, Width, PadWithZero); break; } case 'u': @@ -172,27 +162,25 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, : HaveZ ? va_arg(Args, uptr) : va_arg(Args, unsigned); const bool Upper = (*Cur == 'X'); - Res += appendUnsigned(&Buffer, BufferEnd, UVal, (*Cur == 'u') ? 10 : 16, - Width, PadWithZero, Upper); + appendUnsigned(UVal, (*Cur == 'u') ? 10 : 16, Width, PadWithZero, Upper); break; } case 'p': { RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp); - Res += appendPointer(&Buffer, BufferEnd, va_arg(Args, uptr)); + appendPointer(va_arg(Args, uptr)); break; } case 's': { RAW_CHECK_MSG(!HaveLength, PrintfFormatsHelp); // Only left-justified Width is supported. CHECK(!HaveWidth || LeftJustified); - Res += appendString(&Buffer, BufferEnd, LeftJustified ? -Width : Width, - Precision, va_arg(Args, char *)); + appendString(LeftJustified ? -Width : Width, Precision, + va_arg(Args, char *)); break; } case 'c': { RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp); - Res += - appendChar(&Buffer, BufferEnd, static_cast(va_arg(Args, int))); + String.push_back(static_cast(va_arg(Args, int))); break; } // In Scudo, `s64`/`u64` are supposed to use `lld` and `llu` respectively. @@ -207,19 +195,17 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, if (*Cur == 'd') { DVal = va_arg(Args, s64); - Res += - appendSignedDecimal(&Buffer, BufferEnd, DVal, Width, PadWithZero); + appendSignedDecimal(DVal, Width, PadWithZero); } else { UVal = va_arg(Args, u64); - Res += appendUnsigned(&Buffer, BufferEnd, UVal, 10, Width, PadWithZero, - false); + appendUnsigned(UVal, 10, Width, PadWithZero, false); } break; } case '%': { RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp); - Res += appendChar(&Buffer, BufferEnd, '%'); + String.push_back('%'); break; } default: { @@ -227,35 +213,13 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, } } } - RAW_CHECK(Buffer <= BufferEnd); - appendChar(&Buffer, BufferEnd + 1, '\0'); - return Res; -} - -int formatString(char *Buffer, uptr BufferLength, const char *Format, ...) { - va_list Args; - va_start(Args, Format); - int Res = formatString(Buffer, BufferLength, Format, Args); - va_end(Args); - return Res; -} - -void ScopedString::vappend(const char *Format, va_list Args) { - va_list ArgsCopy; - va_copy(ArgsCopy, Args); - // formatString doesn't currently support a null buffer or zero buffer length, - // so in order to get the resulting formatted string length, we use a one-char - // buffer. - char C[1]; - const uptr AdditionalLength = - static_cast(formatString(C, sizeof(C), Format, Args)) + 1; - const uptr Length = length(); - String.resize(Length + AdditionalLength); - const uptr FormattedLength = static_cast(formatString( - String.data() + Length, String.size() - Length, Format, ArgsCopy)); - RAW_CHECK(data()[length()] == '\0'); - RAW_CHECK(FormattedLength + 1 == AdditionalLength); - va_end(ArgsCopy); + String.push_back('\0'); + if (String.back() != '\0') { + // String truncated, make sure the string is terminated properly. + // This can happen if there is no more memory when trying to resize + // the string. + String.back() = '\0'; + } } void ScopedString::append(const char *Format, ...) { diff --git a/compiler-rt/lib/scudo/standalone/string_utils.h b/compiler-rt/lib/scudo/standalone/string_utils.h index a4cab5268ede..6e00b6377973 100644 --- a/compiler-rt/lib/scudo/standalone/string_utils.h +++ b/compiler-rt/lib/scudo/standalone/string_utils.h @@ -25,17 +25,24 @@ public: String.clear(); String.push_back('\0'); } - void vappend(const char *Format, va_list Args); + void vappend(const char *Format, va_list &Args); void append(const char *Format, ...) FORMAT(2, 3); void output() const { outputRaw(String.data()); } void reserve(size_t Size) { String.reserve(Size + 1); } + uptr capacity() { return String.capacity() - 1; } private: + void appendNumber(u64 AbsoluteValue, u8 Base, u8 MinNumberLength, + bool PadWithZero, bool Negative, bool Upper); + void appendUnsigned(u64 Num, u8 Base, u8 MinNumberLength, bool PadWithZero, + bool Upper); + void appendSignedDecimal(s64 Num, u8 MinNumberLength, bool PadWithZero); + void appendString(int Width, int MaxChars, const char *S); + void appendPointer(u64 ptr_value); + Vector String; }; -int formatString(char *Buffer, uptr BufferLength, const char *Format, ...) - FORMAT(3, 4); void Printf(const char *Format, ...) FORMAT(1, 2); } // namespace scudo diff --git a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp index 7a69ffd9762c..e068c48fc97c 100644 --- a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp @@ -66,6 +66,10 @@ TEST(ScudoStringsTest, Precision) { Str.append("%-6s", "12345"); EXPECT_EQ(Str.length(), strlen(Str.data())); EXPECT_STREQ("12345 ", Str.data()); + Str.clear(); + Str.append("%-8s", "12345"); + EXPECT_EQ(Str.length(), strlen(Str.data())); + EXPECT_STREQ("12345 ", Str.data()); } static void fillString(scudo::ScopedString &Str, scudo::uptr Size) { @@ -123,3 +127,31 @@ TEST(ScudoStringsTest, Padding) { testAgainstLibc("%03d - %03d", 12, 1234); testAgainstLibc("%03d - %03d", -12, -1234); } + +#if defined(__linux__) +#include + +TEST(ScudoStringsTest, CapacityIncreaseFails) { + scudo::ScopedString Str; + + rlimit Limit = {}; + EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit)); + rlimit EmptyLimit = {.rlim_max = Limit.rlim_max}; + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit)); + + // Test requires that the default length is at least 6 characters. + scudo::uptr MaxSize = Str.capacity(); + EXPECT_LE(6, MaxSize); + + for (size_t i = 0; i < MaxSize - 5; i++) { + Str.append("B"); + } + + // Attempt to append past the end of the current capacity. + Str.append("%d", 12345678); + EXPECT_EQ(MaxSize, Str.capacity()); + EXPECT_STREQ("B12345", &Str.data()[MaxSize - 6]); + + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &Limit)); +} +#endif diff --git a/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp b/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp index dc23c2a34713..b7678678d8a2 100644 --- a/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp @@ -41,3 +41,38 @@ TEST(ScudoVectorTest, ResizeReduction) { V.resize(1); EXPECT_EQ(V.size(), 1U); } + +#if defined(__linux__) + +#include + +// Verify that if the reallocate fails, nothing new is added. +TEST(ScudoVectorTest, ReallocateFails) { + scudo::Vector V; + scudo::uptr capacity = V.capacity(); + + // Get the current address space size. + rlimit Limit = {}; + EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit)); + + rlimit EmptyLimit = {.rlim_max = Limit.rlim_max}; + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit)); + + V.resize(capacity); + // Set the last element so we can check it later. + V.back() = '\0'; + + // The reallocate should fail, so the capacity should not change. + V.reserve(capacity + 1000); + EXPECT_EQ(capacity, V.capacity()); + + // Now try to do a push back and verify that the size does not change. + scudo::uptr Size = V.size(); + V.push_back('2'); + EXPECT_EQ(Size, V.size()); + // Verify that the last element in the vector did not change. + EXPECT_EQ('\0', V.back()); + + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &Limit)); +} +#endif diff --git a/compiler-rt/lib/scudo/standalone/vector.h b/compiler-rt/lib/scudo/standalone/vector.h index c0f1ba0eddfa..ca10cc281d77 100644 --- a/compiler-rt/lib/scudo/standalone/vector.h +++ b/compiler-rt/lib/scudo/standalone/vector.h @@ -35,7 +35,9 @@ public: DCHECK_LE(Size, capacity()); if (Size == capacity()) { const uptr NewCapacity = roundUpPowerOfTwo(Size + 1); - reallocate(NewCapacity); + if (!reallocate(NewCapacity)) { + return; + } } memcpy(&Data[Size++], &Element, sizeof(T)); } @@ -51,14 +53,17 @@ public: const T *data() const { return Data; } T *data() { return Data; } constexpr uptr capacity() const { return CapacityBytes / sizeof(T); } - void reserve(uptr NewSize) { + bool reserve(uptr NewSize) { // Never downsize internal buffer. if (NewSize > capacity()) - reallocate(NewSize); + return reallocate(NewSize); + return true; } void resize(uptr NewSize) { if (NewSize > Size) { - reserve(NewSize); + if (!reserve(NewSize)) { + return; + } memset(&Data[Size], 0, sizeof(T) * (NewSize - Size)); } Size = NewSize; @@ -86,13 +91,16 @@ protected: } private: - void reallocate(uptr NewCapacity) { + bool reallocate(uptr NewCapacity) { DCHECK_GT(NewCapacity, 0); DCHECK_LE(Size, NewCapacity); MemMapT NewExternalBuffer; NewCapacity = roundUp(NewCapacity * sizeof(T), getPageSizeCached()); - NewExternalBuffer.map(/*Addr=*/0U, NewCapacity, "scudo:vector"); + if (!NewExternalBuffer.map(/*Addr=*/0U, NewCapacity, "scudo:vector", + MAP_ALLOWNOMEM)) { + return false; + } T *NewExternalData = reinterpret_cast(NewExternalBuffer.getBase()); memcpy(NewExternalData, Data, Size * sizeof(T)); @@ -101,6 +109,7 @@ private: Data = NewExternalData; CapacityBytes = NewCapacity; ExternalBuffer = NewExternalBuffer; + return true; } T *Data = nullptr; -- GitLab From 80bba17914dec52789d2e75ed560acb11cce959a Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Tue, 26 Mar 2024 14:53:04 -0700 Subject: [PATCH 007/541] [libc][FPUtil] fixup missing explicit cast (#86736) The arm32 buildbot reports an error because UInt::operator bool() is explicit, thus an explicit cast is necessary. Link: #85940 --- libc/src/__support/FPUtil/BasicOperations.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index 405755f8b57d..f746d7ac6ad4 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -199,7 +199,7 @@ LIBC_INLINE int canonicalize(T &cx, const T &x) { // Values | | | (−1)**s × m × 2**−16382 bool bit63 = sx.get_implicit_bit(); UInt128 mantissa = sx.get_explicit_mantissa(); - bool bit62 = ((mantissa & (1ULL << 62)) >> 62); + bool bit62 = static_cast((mantissa & (1ULL << 62)) >> 62); int exponent = sx.get_biased_exponent(); if (exponent == 0x7FFF) { if (!bit63 && !bit62) { -- GitLab From 86692258637549ed9f863c3d2ba47b49f61bbc1f Mon Sep 17 00:00:00 2001 From: Jon Chesterfield Date: Tue, 26 Mar 2024 22:33:03 +0000 Subject: [PATCH 008/541] [compiler-rt] Allow building builtins.a without a libc (#86737) compiler-rt may depend on libc (memset etc). Likewise a libc built by clang may depend on compiler-rt builtins. This circular dependency doesn't matter much once they're both compiled. The easy compilation order to build both from source is: 1. install libc headers somewhere 2. build compiler-rt builtins against those headers 3. build libc against compiler-rt builtins This patch relaxes the cmake sanity check to pass without requiring a libc library. That allows the above sequence to work. Otherwise one needs to build a static libc, then use that to pass the compiler-rt cmake check, then build a normal libc. --- compiler-rt/cmake/config-ix.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 46a6fdf8728f..911f48fa1381 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -235,9 +235,9 @@ set(COMPILER_RT_SUPPORTED_ARCH) # Try to compile a very simple source file to ensure we can target the given # platform. We use the results of these tests to build only the various target # runtime libraries supported by our current compilers cross-compiling -# abilities. +# abilities. Avoids using libc as that may not be available yet. set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) -file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main(void) { printf(\"hello, world\"); }\n") +file(WRITE ${SIMPLE_SOURCE} "int main(void) { return 0; }\n") # Detect whether the current target platform is 32-bit or 64-bit, and setup # the correct commandline flags needed to attempt to target 32-bit and 64-bit. -- GitLab From d31278896208d856b277e34bd7e2a63899f0b57b Mon Sep 17 00:00:00 2001 From: "Xiangyang (Mark) Guo" Date: Tue, 26 Mar 2024 15:59:31 -0700 Subject: [PATCH 009/541] [InlineOrder] fix the calculation of Cost for CostBenefitPriority (#86630) getCost() expects that isVariable() is true. https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Analysis/InlineCost.h#L146 Co-authored-by: helloguo --- llvm/lib/Analysis/InlineOrder.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Analysis/InlineOrder.cpp b/llvm/lib/Analysis/InlineOrder.cpp index 09fc4f9a00f4..f156daa2f126 100644 --- a/llvm/lib/Analysis/InlineOrder.cpp +++ b/llvm/lib/Analysis/InlineOrder.cpp @@ -114,7 +114,10 @@ public: CostBenefitPriority(const CallBase *CB, FunctionAnalysisManager &FAM, const InlineParams &Params) { auto IC = getInlineCostWrapper(const_cast(*CB), FAM, Params); - Cost = IC.getCost(); + if (IC.isVariable()) + Cost = IC.getCost(); + else + Cost = IC.isNever() ? INT_MAX : INT_MIN; StaticBonusApplied = IC.getStaticBonusApplied(); CostBenefit = IC.getCostBenefit(); } -- GitLab From 09155ac290b0906ac8011c87ee43d7c7a2710387 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 26 Mar 2024 16:23:26 -0700 Subject: [PATCH 010/541] [LegalizeDAG] Remove unneeded temporary SDValues from PerformInsertVectorEltInMemory. NFC There were 3 temporaries that just renamed the 3 well name arguments to the function to Tmp1-3. Looks like this was done when the code was extracted from elsewhere into a separate function 15 years ago. --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 808e3c622033..b1f6fd6f3c72 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -386,17 +386,13 @@ SDValue SelectionDAGLegalize::PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, const SDLoc &dl) { - SDValue Tmp1 = Vec; - SDValue Tmp2 = Val; - SDValue Tmp3 = Idx; - // If the target doesn't support this, we have to spill the input vector // to a temporary stack slot, update the element, then reload it. This is // badness. We could also load the value into a vector register (either // with a "move to register" or "extload into register" instruction, then // permute it into place, if the idx is a constant and if the idx is // supported by the target. - EVT VT = Tmp1.getValueType(); + EVT VT = Vec.getValueType(); EVT EltVT = VT.getVectorElementType(); SDValue StackPtr = DAG.CreateStackTemporary(VT); @@ -404,14 +400,14 @@ SDValue SelectionDAGLegalize::PerformInsertVectorEltInMemory(SDValue Vec, // Store the vector. SDValue Ch = DAG.getStore( - DAG.getEntryNode(), dl, Tmp1, StackPtr, + DAG.getEntryNode(), dl, Vec, StackPtr, MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI)); - SDValue StackPtr2 = TLI.getVectorElementPointer(DAG, StackPtr, VT, Tmp3); + SDValue StackPtr2 = TLI.getVectorElementPointer(DAG, StackPtr, VT, Idx); // Store the scalar value. Ch = DAG.getTruncStore( - Ch, dl, Tmp2, StackPtr2, + Ch, dl, Val, StackPtr2, MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT); // Load the updated vector. return DAG.getLoad(VT, dl, Ch, StackPtr, MachinePointerInfo::getFixedStack( -- GitLab From b1a633bc014a845a58f0f3c4e442219051646c19 Mon Sep 17 00:00:00 2001 From: Alex MacLean Date: Tue, 26 Mar 2024 16:39:32 -0700 Subject: [PATCH 011/541] [NFC][NVPTX] remove truncating c-style cast (#85889) While a stack size large enough to cause this truncation to be a problem would certainly cause other issues and not produce a valid program anyway, this cast is triggering our Coverity static analysis. Removing it seems cleaner. --- llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp index 2783b1e0ec73..ece9821a2d0d 100644 --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -1719,7 +1719,7 @@ void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters( // Emit the Fake Stack Object const MachineFrameInfo &MFI = MF.getFrameInfo(); - int NumBytes = (int) MFI.getStackSize(); + int64_t NumBytes = MFI.getStackSize(); if (NumBytes) { O << "\t.local .align " << MFI.getMaxAlign().value() << " .b8 \t" << DEPOTNAME << getFunctionNumber() << "[" << NumBytes << "];\n"; -- GitLab From 7db40463229bb1c9fb15b2107d878fe70d1eda65 Mon Sep 17 00:00:00 2001 From: Vadim Paretsky Date: Tue, 26 Mar 2024 16:41:31 -0700 Subject: [PATCH 012/541] [OpenMP] add loop collapse tests (#86243) This PR adds loop collapse tests ported from MSVC. --------- Co-authored-by: Vadim Paretsky --- openmp/runtime/src/kmp_collapse.cpp | 11 +- .../test/worksharing/for/collapse_test.inc | 201 ++++++++++++++++++ .../for/omp_collapse_many_GELTGT_int.c | 65 ++++++ .../for/omp_collapse_many_GTGEGT_int.c | 71 +++++++ .../for/omp_collapse_many_LTLEGE_int.c | 66 ++++++ .../worksharing/for/omp_collapse_many_int.c | 73 +++++++ .../worksharing/for/omp_collapse_one_int.c | 32 +++ 7 files changed, 511 insertions(+), 8 deletions(-) create mode 100644 openmp/runtime/test/worksharing/for/collapse_test.inc create mode 100644 openmp/runtime/test/worksharing/for/omp_collapse_many_GELTGT_int.c create mode 100644 openmp/runtime/test/worksharing/for/omp_collapse_many_GTGEGT_int.c create mode 100644 openmp/runtime/test/worksharing/for/omp_collapse_many_LTLEGE_int.c create mode 100644 openmp/runtime/test/worksharing/for/omp_collapse_many_int.c create mode 100644 openmp/runtime/test/worksharing/for/omp_collapse_one_int.c diff --git a/openmp/runtime/src/kmp_collapse.cpp b/openmp/runtime/src/kmp_collapse.cpp index 569d2c150831..e63a98081db9 100644 --- a/openmp/runtime/src/kmp_collapse.cpp +++ b/openmp/runtime/src/kmp_collapse.cpp @@ -1517,16 +1517,11 @@ void kmp_handle_upper_triangle_matrix( kmp_uint64 iter_with_current = iter_before_current + iter_current; // calculate the outer loop lower bound (lbo) which is the max outer iv value // that gives the number of iterations that is equal or just below the total - // number of iterations executed by the previous threads, for less_than - // (1-based) inner loops (inner_ub0 == -1) it will be i.e. - // lbo*(lbo-1)/2<=iter_before_current => lbo^2-lbo-2*iter_before_current<=0 - // for less_than_equal (0-based) inner loops (inner_ub == 0) it will be: - // i.e. lbo*(lbo+1)/2<=iter_before_current => - // lbo^2+lbo-2*iter_before_current<=0 both cases can be handled similarily - // using a parameter to control the equatio sign + // number of iterations executed by the previous threads: + // lbo*(lbo+1)/2<=iter_before_current => + // lbo^2+lbo-2*iter_before_current<=0 kmp_uint64 lower_bound_outer = (kmp_uint64)(sqrt_newton_approx(1 + 8 * iter_before_current) + 1) / 2 - 1; - ; // calculate the inner loop lower bound which is the remaining number of // iterations required to hit the total number of iterations executed by the // previous threads giving the starting point of this thread diff --git a/openmp/runtime/test/worksharing/for/collapse_test.inc b/openmp/runtime/test/worksharing/for/collapse_test.inc new file mode 100644 index 000000000000..de0e7e4e57f3 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/collapse_test.inc @@ -0,0 +1,201 @@ +#include +#include +#include +#include + +#define LOOP_IV_TYPE0 LOOP_TYPES +#define LOOP_TYPE0 LOOP_TYPES +#define LOOP_STYPE0 LOOP_TYPES + +#define LOOP_IV_TYPE1 LOOP_TYPES +#define LOOP_TYPE1 LOOP_TYPES +#define LOOP_STYPE1 LOOP_TYPES + +#define LOOP_IV_TYPE2 LOOP_TYPES +#define LOOP_TYPE2 LOOP_TYPES +#define LOOP_STYPE2 LOOP_TYPES + +#define MAX_THREADS 256 + +#if defined VERBOSE +#define PRINTF printf +#else +#define PRINTF +#endif + +LOOP_TYPE0 iLB, iUB; +LOOP_TYPE1 jA0, jB0; +LOOP_TYPE2 kA0, kB0; + +LOOP_STYPE0 iStep; +LOOP_STYPE1 jA1, jB1, jStep; +LOOP_STYPE2 kA1, kB1, kStep; + +// We can check <=, <, >=, > (!= has different pattern) +// Additional definition of LOOP_LEi, LOOP_LTi, etc. is helpful to build calls +// of the test from main + +#if defined LOOP_LE0 +#define COMPARE0 <= +#elif defined LOOP_LT0 +#define COMPARE0 < +#elif defined LOOP_GE0 +#define COMPARE0 >= +#elif defined LOOP_GT0 +#define COMPARE0 > +#endif + +#if defined LOOP_LE1 +#define COMPARE1 <= +#elif defined LOOP_LT1 +#define COMPARE1 < +#elif defined LOOP_GE1 +#define COMPARE1 >= +#elif defined LOOP_GT1 +#define COMPARE1 > +#endif + +#if defined LOOP_LE2 +#define COMPARE2 <= +#elif defined LOOP_LT2 +#define COMPARE2 < +#elif defined LOOP_GE2 +#define COMPARE2 >= +#elif defined LOOP_GT2 +#define COMPARE2 > +#endif + +typedef struct { + LOOP_IV_TYPE0 i; + LOOP_IV_TYPE1 j; + LOOP_IV_TYPE2 k; +} spaceType; + +spaceType *AllocSpace(unsigned size) { + + spaceType *p = (spaceType *)malloc(size * sizeof(spaceType)); + memset(p, 0, size * sizeof(spaceType)); + return p; +} + +void FreeSpace(spaceType *space) { free(space); } + +// record an iteration +void Set(spaceType *space, unsigned count, unsigned trueCount, LOOP_IV_TYPE0 i, + LOOP_IV_TYPE1 j, LOOP_IV_TYPE0 k) { + if (count > trueCount) { + // number of iterations exceeded + // will be reported with checks + return; + } + space[count - 1].i = i; + space[count - 1].j = j; + space[count - 1].k = k; +} +int test() { + int pass = 1; + LOOP_IV_TYPE0 i; + LOOP_IV_TYPE1 j; + LOOP_IV_TYPE2 k; + + spaceType *openmpSpace; + spaceType *scalarSpace; + + unsigned trueCount = 0; + unsigned openmpCount = 0; + unsigned scalarCount = 0; + unsigned uselessThreadsOpenMP = 0; + unsigned usefulThreadsOpenMP = 0; + unsigned chunkSizesOpenmp[MAX_THREADS] = {0}; + + unsigned num_threads = omp_get_max_threads(); + if (num_threads > MAX_THREADS) + num_threads = MAX_THREADS; + omp_set_num_threads(num_threads); + + // count iterations and allocate space + LOOP { ++trueCount; } + + openmpSpace = AllocSpace(trueCount); + scalarSpace = AllocSpace(trueCount); + + // fill the scalar (compare) space + LOOP { + ++scalarCount; + Set(scalarSpace, scalarCount, trueCount, i, j, k); + } + + // test run body: + // perform and record OpenMP iterations and thread use +#pragma omp parallel num_threads(num_threads) + { +#pragma omp for collapse(3) private(i, j, k) + LOOP { + unsigned count; + unsigned gtid = omp_get_thread_num(); +#pragma omp atomic update + ++chunkSizesOpenmp[gtid]; +#pragma omp atomic capture + count = ++openmpCount; + Set(openmpSpace, count, trueCount, i, j, k); + } + } + + // check for the right number of iterations processed + // (only need to check for less, greater is checked when recording) + if (openmpCount < trueCount) { + PRINTF("OpenMP FAILURE: Openmp processed fewer iterations: %d vs %d\n", + openmpCount, trueCount); + pass = 0; + } else if (openmpCount > trueCount) { + PRINTF("OpenMP FAILURE: Openmp processed more iterations: %d vs %d\n", + openmpCount, trueCount); + pass = 0; + } + + // check openMP for iteration correctnes against scalar + for (unsigned i = 0; i < trueCount; i++) { + unsigned j; + for (j = 0; j < openmpCount; j++) { + if ((scalarSpace[i].i == openmpSpace[j].i) && + (scalarSpace[i].j == openmpSpace[j].j) && + (scalarSpace[i].k == openmpSpace[j].k)) { + break; + } + } + if (j == openmpCount) { + PRINTF("OpenMP FAILURE: (%d %d %d) not processed\n", scalarSpace[i].i, + scalarSpace[i].j, scalarSpace[i].k); + pass = 0; + } + } + + // check for efficient thread use + for (unsigned i = 0; i < num_threads; ++i) { + if (chunkSizesOpenmp[i] == 0) { + ++uselessThreadsOpenMP; + } + } + + // a check to see if at least more than one thread was used (weakish) + if ((uselessThreadsOpenMP == num_threads - 1) && (trueCount > 1)) { + PRINTF("OpenMP FAILURE: threads are not used\n"); + pass = 0; + } + +#if 0 + // a check to see if the load was spread more or less evenly so that + // when there was more work than threads each one got at least something + // (stronger, but may currently fail for a general collapse case) + if ((trueCount >= num_threads) && (uselessThreadsOpenMP > 0)) { + PRINTF("OpenMP FAILURE: %d threads not used with %d iterations\n", + uselessThreadsOpenMP, openmpCount); + pass = 0; + } +#endif + + // clean up space + FreeSpace(openmpSpace); + FreeSpace(scalarSpace); + return pass; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_GELTGT_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_GELTGT_int.c new file mode 100644 index 000000000000..77b2d6918d87 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_GELTGT_int.c @@ -0,0 +1,65 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define COMPARE0 >= +#define COMPARE1 < +#define COMPARE2 > +#define LOOP \ + for (i = iLB; i COMPARE0 iUB; i += iStep) \ + for (j = jA0; j COMPARE1 jB0; j += jStep) \ + for (k = kA0; k COMPARE2 kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail; + + iLB = 3; + iUB = -2; + jA0 = -3; + jA1 = 0; + jB0 = -6; + jB1 = 0; + kA0 = -2; + kA1 = 0; + kB0 = -4; + kB1 = 0; + iStep = -1; + jStep = -1; + kStep = -4; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = (test() == 0); + + if (!fail) { + for (iStep = -3; iStep >= -6; iStep -= 2) { + for (jA0 = -6; jA0 <= 6; jA0 += 3) { + for (jB0 = -3; jB0 <= 10; jB0 += 3) { + for (jStep = 1; jStep <= 10; jStep += 2) { + for (kA0 = -2; kA0 <= 4; ++kA0) { + for (kB0 = -4; kB0 <= 2; ++kB0) { + for (kStep = -2; kStep >= -10; kStep -= 4) { + { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_GTGEGT_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_GTGEGT_int.c new file mode 100644 index 000000000000..985211172e62 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_GTGEGT_int.c @@ -0,0 +1,71 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define COMPARE0 > +#define COMPARE1 >= +#define COMPARE2 > + +#define DLOOP_GT0 +#define DLOOP_GE1 +#define DLOOP_GT2 + +#define LOOP \ + for (i = iLB; i COMPARE0 iUB; i += iStep) \ + for (j = jA0; j COMPARE1 jB0; j += jStep) \ + for (k = kA0; k COMPARE2 kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail; + + iLB = 3; + iUB = -2; + jA0 = -3; + jA1 = 0; + jB0 = -6; + jB1 = 0; + kA0 = -2; + kA1 = 0; + kB0 = -4; + kB1 = 0; + iStep = -1; + jStep = -1; + kStep = -4; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = (test() == 0); + + if (!fail) { + + for (iStep = -3; iStep >= -6; iStep -= 2) { + for (jA0 = -3; jA0 <= 10; jA0 += 3) { + for (jB0 = -6; jB0 <= 6; jB0 += 3) { + for (jStep = -1; jStep >= -10; jStep -= 2) { + for (kA0 = -2; kA0 <= 4; ++kA0) { + for (kB0 = -4; kB0 <= 2; ++kB0) { + for (kStep = -2; kStep >= -10; kStep -= 4) { + { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_LTLEGE_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_LTLEGE_int.c new file mode 100644 index 000000000000..47e3b42226c8 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_LTLEGE_int.c @@ -0,0 +1,66 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define COMPARE0 < +#define COMPARE1 <= +#define COMPARE2 >= +#define LOOP \ + for (i = iLB; i COMPARE0 iUB; i += iStep) \ + for (j = jA0; j COMPARE1 jB0; j += jStep) \ + for (k = kA0; k COMPARE2 kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail; + + iLB = -2; + iUB = 3; + jA0 = -3; + jA1 = 0; + jB0 = -6; + jB1 = 0; + kA0 = -2; + kA1 = 0; + kB0 = -4; + kB1 = 0; + iStep = -1; + jStep = -1; + kStep = -4; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = (test() == 0); + + if (!fail) { + + for (iStep = 2; iStep <= 6; iStep += 2) { + for (jA0 = -6; jA0 <= 6; jA0 += 3) { + for (jB0 = -3; jB0 <= 10; jB0 += 3) { + for (jStep = 1; jStep <= 10; jStep += 2) { + for (kA0 = -2; kA0 <= 4; ++kA0) { + for (kB0 = -4; kB0 <= 2; ++kB0) { + for (kStep = -2; kStep >= -10; kStep -= 4) { + { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_int.c new file mode 100644 index 000000000000..4455602df8a2 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_int.c @@ -0,0 +1,73 @@ +// RUN: %libomp-compile-and-run +// XFAIL: true + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define LOOP \ + for (i = iLB; i <= iUB; i += iStep) \ + for (j = i * jA1 + jA0; j <= i * jB1 + jB0; j += jStep) \ + for (k = j * kA1 + kA0; k <= j * kB1 + kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail = 0; + + iLB = -2; + iUB = 3; + jA0 = -7; + jA1 = -1; + jB0 = 13; + jB1 = 3; + kA0 = -20; + kA1 = -2; + kB0 = 111; + kB1 = -1; + iStep = 5; + jStep = 9; + kStep = 10; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = fail || (test() == 0); + + if (!fail) { + + // NOTE: if a loop on some level won't execute for all iterations of an + // outer loop, it still should work. Runtime doesn't require lower bounds to + // be <= upper bounds for all possible i, j, k. + + iLB = -2; + iUB = 3; + jA0 = -7; + jB0 = 5; + kA0 = -13; + kB0 = 37; + + for (kA1 = -2; kA1 <= 2; ++kA1) { // <= + for (kB1 = -2; kB1 <= 2; ++kB1) { + for (jA1 = -3; jA1 <= 3; ++jA1) { + for (jB1 = -3; jB1 <= 3; ++jB1) { + for (iStep = 1; iStep <= 3; ++iStep) { + for (jStep = 2; jStep <= 6; jStep += 2) { + for (kStep = 2; kStep <= 8; kStep += 3) { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_one_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_one_int.c new file mode 100644 index 000000000000..437d4bff31eb --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_one_int.c @@ -0,0 +1,32 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define LOOP \ + for (i = iLB; i <= iUB; i += iStep) \ + for (j = i + jA0; j <= i + jB0; j += jStep) \ + for (k = j + kA0; k <= j + kB0; k += kStep) + +#include "collapse_test.inc" + +int main() { + int fail; + iLB = -2; + iUB = 3; + jA0 = -7; + jB0 = 13; + kA0 = -20; + kB0 = 111; + iStep = 5; + jStep = 9; + kStep = 10; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jB0=%d; kA0=%d; kB0=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jB0, kA0, kB0, iStep, jStep, kStep); + fail = (test() == 0); + return fail; +} -- GitLab From c43932ebdc407ed9633f7468dcb061b635e99a8d Mon Sep 17 00:00:00 2001 From: SevenIsSeven <150881358+SevenIsSeven@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:05:08 +0900 Subject: [PATCH 013/541] fix build error in MSVC build (#86622) This commit(https://github.com/llvm/llvm-project/pull/84738) introduced following compile warning then treated-as-error in MSVC build. >>>"'^': unsafe mix of type 'unsigned int' and type 'bool' in operation" --------- Co-authored-by: Seven --- llvm/include/llvm/IR/BasicBlock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h index 0eea4cdccca5..0c5a07bde4ec 100644 --- a/llvm/include/llvm/IR/BasicBlock.h +++ b/llvm/include/llvm/IR/BasicBlock.h @@ -791,7 +791,7 @@ template <> struct DenseMapInfo { static unsigned getHashValue(const BasicBlock::iterator &It) { return DenseMapInfo::getHashValue( reinterpret_cast(It.getNodePtr())) ^ - It.getHeadBit(); + (unsigned)It.getHeadBit(); } static bool isEqual(const BasicBlock::iterator &LHS, -- GitLab From 3324f4d4f4bd82bc9fd43062d21a450671a3531b Mon Sep 17 00:00:00 2001 From: Aart Bik Date: Tue, 26 Mar 2024 17:16:03 -0700 Subject: [PATCH 014/541] [mlir][sparse] avoid incompatible linalg fuse-into-consumer (#86752) This fixes an "infinite" loop bug, where the incoming IR was repeatedly rewritten while adding identical cast operations. The test for compatible types should include the notion of an encoding. If it differs, then a naive fusion into the consumer is invalid. --- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 4 ++ .../SparseTensor/no_fold_into_consumer.mlir | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 mlir/test/Dialect/SparseTensor/no_fold_into_consumer.mlir diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index dc8843aa4e1e..38a9ad60bb79 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -276,6 +276,10 @@ bool mlir::tensor::preservesStaticInformation(Type source, Type target) { if (sourceType.getRank() != targetType.getRank()) return false; + // Requires same encoding. + if (sourceType.getEncoding() != targetType.getEncoding()) + return false; + // If cast is towards more static sizes along any dimension, don't fold. for (auto t : llvm::zip(sourceType.getShape(), targetType.getShape())) { if (!ShapedType::isDynamic(std::get<0>(t)) && diff --git a/mlir/test/Dialect/SparseTensor/no_fold_into_consumer.mlir b/mlir/test/Dialect/SparseTensor/no_fold_into_consumer.mlir new file mode 100644 index 000000000000..bbc7f397e793 --- /dev/null +++ b/mlir/test/Dialect/SparseTensor/no_fold_into_consumer.mlir @@ -0,0 +1,47 @@ +// RUN: mlir-opt %s --canonicalize --pre-sparsification-rewrite | FileCheck %s + +#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)> + +#sparse = #sparse_tensor.encoding<{ + map = (d0, d1, d2) -> + (d0 : compressed(nonunique), + d1 : singleton(nonunique, soa), + d2 : singleton(soa)), + posWidth = 64, + crdWidth = 64 +}> + + +module { + // + // This IR should not end up in an infinite loop trying to fold + // the linalg producer into the tensor cast consumer (even though + // static sizes can fold, the different encodings cannot). The + // cast was sloppy to begin with (but it has been observed by + // external sources) and can be easily repaired by the sparsifier. + // + // CHECK-LABEL: func @avoid_fold + // CHECK: arith.constant + // CHECK: tensor.empty() + // CHECK: linalg.generic + // CHECK: sparse_tensor.convert + // CHECK: return + // + func.func @avoid_fold(%0: tensor<10x20x30xf64, #sparse>) -> tensor<10x20x30xf64, #sparse> { + %1 = tensor.empty() : tensor<10x20x30xf64> + %2 = linalg.generic { indexing_maps = [#map, #map], + iterator_types = ["parallel", "parallel", "parallel"] + } + ins (%0 : tensor<10x20x30xf64, #sparse>) + outs(%1 : tensor<10x20x30xf64>) { + ^bb0(%in: f64, %out: f64): + %cst = arith.constant 0.000000e+00 : f64 + %4 = arith.cmpf ugt, %in, %cst : f64 + %5 = arith.select %4, %in, %cst : f64 + linalg.yield %5 : f64 + } -> tensor<10x20x30xf64> + %cast = tensor.cast %2 : tensor<10x20x30xf64> to tensor<10x20x30xf64, #sparse> + return %cast : tensor<10x20x30xf64, #sparse> + } +} + -- GitLab From 54a9f0e441c7cc3c954d24cfde00cb933306a9e9 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Tue, 26 Mar 2024 20:17:22 -0400 Subject: [PATCH 015/541] [RISCV][GISEL] Legalize, regbankselect, and instruction-select G_VSCALE (#85967) G_VSCALE should be lowered using VLENB. If the type is not sXLen it should be lowered using a G_VSCALE on the narrow type and a G_MUL. regbank select and instruction select are straightforward so we really only need to add tests to show it works. --- .../CodeGen/GlobalISel/MachineIRBuilder.h | 11 + .../CodeGen/GlobalISel/LegalizerHelper.cpp | 29 +- .../CodeGen/GlobalISel/MachineIRBuilder.cpp | 7 + .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 48 +++ .../Target/RISCV/GISel/RISCVLegalizerInfo.h | 1 + llvm/lib/Target/RISCV/RISCVInstrGISel.td | 8 + .../instruction-select/rvv/vscale32.mir | 300 ++++++++++++++++++ .../instruction-select/rvv/vscale64.mir | 139 ++++++++ .../legalizer/rvv/legalize-vscale-rv32.mir | 228 +++++++++++++ .../legalizer/rvv/legalize-vscale-rv64.mir | 110 +++++++ .../regbankselect/rvv/vscale-rv32.mir | 48 +++ .../regbankselect/rvv/vscale-rv64.mir | 25 ++ 12 files changed, 953 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale32.mir create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale64.mir create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv32.mir create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv64.mir create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv32.mir create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv64.mir diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 3ba036ae713f..16a7fc446fbe 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1165,6 +1165,17 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildVScale(const DstOp &Res, const ConstantInt &MinElts); + /// Build and insert \p Res = G_VSCALE \p MinElts + /// + /// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts + /// into \p Res. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildVScale(const DstOp &Res, const APInt &MinElts); + /// Build and insert a G_INTRINSIC instruction. /// /// There are four different opcodes based on combinations of whether the diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index c3a23ea0ad37..4981d7b80b0b 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1699,6 +1699,20 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, case TargetOpcode::G_FLDEXP: case TargetOpcode::G_STRICT_FLDEXP: return narrowScalarFLDEXP(MI, TypeIdx, NarrowTy); + case TargetOpcode::G_VSCALE: { + Register Dst = MI.getOperand(0).getReg(); + LLT Ty = MRI.getType(Dst); + + // Assume VSCALE(1) fits into a legal integer + const APInt One(NarrowTy.getSizeInBits(), 1); + auto VScaleBase = MIRBuilder.buildVScale(NarrowTy, One); + auto ZExt = MIRBuilder.buildZExt(Ty, VScaleBase); + auto C = MIRBuilder.buildConstant(Ty, *MI.getOperand(1).getCImm()); + MIRBuilder.buildMul(Dst, ZExt, C); + + MI.eraseFromParent(); + return Legalized; + } } } @@ -2966,7 +2980,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { case TargetOpcode::G_VECREDUCE_FMIN: case TargetOpcode::G_VECREDUCE_FMAX: case TargetOpcode::G_VECREDUCE_FMINIMUM: - case TargetOpcode::G_VECREDUCE_FMAXIMUM: + case TargetOpcode::G_VECREDUCE_FMAXIMUM: { if (TypeIdx != 0) return UnableToLegalize; Observer.changingInstr(MI); @@ -2980,6 +2994,19 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { Observer.changedInstr(MI); return Legalized; } + case TargetOpcode::G_VSCALE: { + MachineOperand &SrcMO = MI.getOperand(1); + LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); + const APInt &SrcVal = SrcMO.getCImm()->getValue(); + // The CImm is always a signed value + const APInt Val = SrcVal.sext(WideTy.getSizeInBits()); + Observer.changingInstr(MI); + SrcMO.setCImm(ConstantInt::get(Ctx, Val)); + widenScalarDst(MI, WideTy); + Observer.changedInstr(MI); + return Legalized; + } + } } static void getUnmergePieces(SmallVectorImpl &Pieces, diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index f7aaa0f02efc..f2665e25d195 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -811,6 +811,13 @@ MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, return VScale; } +MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, + const APInt &MinElts) { + ConstantInt *CI = + ConstantInt::get(getMF().getFunction().getContext(), MinElts); + return buildVScale(Res, *CI); +} + static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) { if (HasSideEffects && IsConvergent) return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS; diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index 941ad752bfd9..9a388f4cd271 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -408,6 +408,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .clampScalar(0, s32, sXLen) .lowerForCartesianProduct({s32, sXLen, p0}, {p0}); + getActionDefinitionsBuilder(G_VSCALE) + .clampScalar(0, sXLen, sXLen) + .customFor({sXLen}); + getLegacyLegalizerInfo().computeTables(); } @@ -529,6 +533,48 @@ bool RISCVLegalizerInfo::shouldBeInConstantPool(APInt APImm, return !(!SeqLo.empty() && (SeqLo.size() + 2) <= STI.getMaxBuildIntsCost()); } +bool RISCVLegalizerInfo::legalizeVScale(MachineInstr &MI, + MachineIRBuilder &MIB) const { + const LLT XLenTy(STI.getXLenVT()); + Register Dst = MI.getOperand(0).getReg(); + + // We define our scalable vector types for lmul=1 to use a 64 bit known + // minimum size. e.g. . VLENB is in bytes so we calculate + // vscale as VLENB / 8. + static_assert(RISCV::RVVBitsPerBlock == 64, "Unexpected bits per block!"); + if (STI.getRealMinVLen() < RISCV::RVVBitsPerBlock) + // Support for VLEN==32 is incomplete. + return false; + + // We assume VLENB is a multiple of 8. We manually choose the best shift + // here because SimplifyDemandedBits isn't always able to simplify it. + uint64_t Val = MI.getOperand(1).getCImm()->getZExtValue(); + if (isPowerOf2_64(Val)) { + uint64_t Log2 = Log2_64(Val); + if (Log2 < 3) { + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + MIB.buildLShr(Dst, VLENB, MIB.buildConstant(XLenTy, 3 - Log2)); + } else if (Log2 > 3) { + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + MIB.buildShl(Dst, VLENB, MIB.buildConstant(XLenTy, Log2 - 3)); + } else { + MIB.buildInstr(RISCV::G_READ_VLENB, {Dst}, {}); + } + } else if ((Val % 8) == 0) { + // If the multiplier is a multiple of 8, scale it down to avoid needing + // to shift the VLENB value. + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + MIB.buildMul(Dst, VLENB, MIB.buildConstant(XLenTy, Val / 8)); + } else { + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + auto VScale = MIB.buildLShr(XLenTy, VLENB, MIB.buildConstant(XLenTy, 3)); + MIB.buildMul(Dst, VScale, MIB.buildConstant(XLenTy, Val)); + } + + MI.eraseFromParent(); + return true; +} + bool RISCVLegalizerInfo::legalizeCustom( LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const { @@ -586,6 +632,8 @@ bool RISCVLegalizerInfo::legalizeCustom( } case TargetOpcode::G_VASTART: return legalizeVAStart(MI, MIRBuilder); + case TargetOpcode::G_VSCALE: + return legalizeVScale(MI, MIRBuilder); } llvm_unreachable("expected switch to return"); diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h index 323426034827..e2a98c8d2c73 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h @@ -42,6 +42,7 @@ private: GISelChangeObserver &Observer) const; bool legalizeVAStart(MachineInstr &MI, MachineIRBuilder &MIRBuilder) const; + bool legalizeVScale(MachineInstr &MI, MachineIRBuilder &MIB) const; }; } // end namespace llvm #endif diff --git a/llvm/lib/Target/RISCV/RISCVInstrGISel.td b/llvm/lib/Target/RISCV/RISCVInstrGISel.td index ede8c9809833..54e22d625781 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrGISel.td +++ b/llvm/lib/Target/RISCV/RISCVInstrGISel.td @@ -24,3 +24,11 @@ def G_FCLASS : RISCVGenericInstruction { let hasSideEffects = false; } def : GINodeEquiv; + +// Pseudo equivalent to a RISCVISD::READ_VLENB. +def G_READ_VLENB : RISCVGenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins); + let hasSideEffects = false; +} +def : GINodeEquiv; diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale32.mir new file mode 100644 index 000000000000..27dfb3fdda9d --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale32.mir @@ -0,0 +1,300 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v,+m -run-pass=instruction-select \ +# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: test_1_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 3 + %0:gprb(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_2_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 2 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 2 + %0:gprb(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_3_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 3 + %3:gprb(s32) = G_LSHR %1, %2(s32) + %4:gprb(s32) = G_CONSTANT i32 3 + %0:gprb(s32) = G_MUL %3, %4 + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_4_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 1 + %0:gprb(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_8_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: $x10 = COPY [[PseudoReadVLENB]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s32) = G_READ_VLENB + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_16_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SLLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 1 + %0:gprb(s32) = G_SHL %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_40_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[PseudoReadVLENB]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 5 + %0:gprb(s32) = G_MUL %1, %2 + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_1_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 1 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 1 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_2_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 2 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 2 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_3_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 3 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_4_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 4 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 4 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_8_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 8 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 8 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_16_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 16 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 16 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_40_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 40 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 40 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale64.mir new file mode 100644 index 000000000000..4a96be2471f8 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale64.mir @@ -0,0 +1,139 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv64 -mattr=+v,+m -run-pass=instruction-select \ +# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: test_1 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 3 + %2:gprb(s64) = G_LSHR %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 2 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 2 + %2:gprb(s64) = G_LSHR %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_3 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 3 + %2:gprb(s64) = G_LSHR %0, %1(s64) + %3:gprb(s64) = G_CONSTANT i64 3 + %4:gprb(s64) = G_MUL %2, %3 + $x10 = COPY %4(s64) + PseudoRET implicit $x10 + +... +--- +name: test_4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 1 + %2:gprb(s64) = G_LSHR %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_8 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: $x10 = COPY [[PseudoReadVLENB]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + $x10 = COPY %0(s64) + PseudoRET implicit $x10 + +... +--- +name: test_16 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SLLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 1 + %2:gprb(s64) = G_SHL %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_40 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[PseudoReadVLENB]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 5 + %2:gprb(s64) = G_MUL %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv32.mir new file mode 100644 index 000000000000..899f7955a273 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv32.mir @@ -0,0 +1,228 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v,+m -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: test_1_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_1_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 1 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_2_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_2_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 2 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_3_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_3_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 3 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_4_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_4_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 4 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_8_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_8_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: $x10 = COPY [[READ_VLENB]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 8 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_16_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_16_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[SHL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 16 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_40_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_40_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[READ_VLENB]], [[C]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 40 + $x10 = COPY %0 + PseudoRET implicit $x10 +... + +--- +name: test_1_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 1 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_2_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 2 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_3_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 3 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_4_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 4 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_8_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 8 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_16_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 16 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_40_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 40 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 40 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv64.mir new file mode 100644 index 000000000000..c0453a04a181 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv64.mir @@ -0,0 +1,110 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv64 -mattr=+v,+m -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: test_1 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_1 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 1 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_2 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_2 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 2 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_3 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_3 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 3 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_4 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_4 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 4 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_8 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_8 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: $x10 = COPY [[READ_VLENB]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 8 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_16 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_16 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[SHL]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 16 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_40 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_40 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[READ_VLENB]], [[C]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 40 + $x10 = COPY %0 + PseudoRET implicit $x10 +... + + diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv32.mir new file mode 100644 index 000000000000..ae3bb0a18020 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv32.mir @@ -0,0 +1,48 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=riscv32 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck %s + +--- +name: test_s32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:gprb(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:gprb(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s32) = G_READ_VLENB + %2:_(s32) = G_CONSTANT i32 3 + %0:_(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_s64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:gprb(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:gprb(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gprb(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:_(s32) = G_READ_VLENB + %18:_(s32) = G_CONSTANT i32 3 + %2:_(s32) = G_LSHR %17, %18(s32) + %15:_(s32) = G_CONSTANT i32 1 + %9:_(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... + diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv64.mir new file mode 100644 index 000000000000..a7446d976f25 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv64.mir @@ -0,0 +1,25 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv64 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck %s + +--- +name: test +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test + ; CHECK: [[READ_VLENB:%[0-9]+]]:gprb(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:gprb(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s64) = G_READ_VLENB + %2:_(s64) = G_CONSTANT i64 3 + %0:_(s64) = G_LSHR %1, %2(s64) + $x10 = COPY %0(s64) + PseudoRET implicit $x10 + +... + -- GitLab From 373d8755140df0c760e9c292c5f88479cdda6f4c Mon Sep 17 00:00:00 2001 From: Pavel Kosov Date: Wed, 27 Mar 2024 03:25:33 +0300 Subject: [PATCH 016/541] =?UTF-8?q?[cfi][CodeGen]=20Call=20SetLLVMFunction?= =?UTF-8?q?Attributes{,ForDefinition}=20on=20=5F=5Fcf=E2=80=A6=20(#78253)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …i_check This causes __cfi_check, just as __cfi_check_fail, to get the proper target-specific attributes, in particular uwtable for unwind table generation. Previously, nounwind attribute could be inferred for __cfi_check, which caused it to lose its unwind table even with -funwind-table option. ~~ Huawei RRI, OS Lab Co-authored-by: Nikolai Kholiavin --- clang/docs/ReleaseNotes.rst | 4 ++++ clang/lib/CodeGen/CGExpr.cpp | 21 +++++++++++++++++++-- clang/test/CodeGen/cfi-check-attrs.c | 5 +++++ clang/test/CodeGen/cfi-check-fail.c | 2 +- 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGen/cfi-check-attrs.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 01abe2b39e87..0dd026a5de5c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -626,6 +626,10 @@ Sanitizers manually disable potentially noisy signed integer overflow checks with ``-fno-sanitize=signed-integer-overflow`` +- ``-fsanitize=cfi -fsanitize-cfi-cross-dso`` (cross-DSO CFI instrumentation) + now generates the ``__cfi_check`` function with proper target-specific + attributes, for example allowing unwind table generation. + Python Binding Changes ---------------------- diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85f5d739cef4..6491835cf8ef 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3663,12 +3663,29 @@ void CodeGenFunction::EmitCfiSlowPathCheck( // symbol in LTO mode. void CodeGenFunction::EmitCfiCheckStub() { llvm::Module *M = &CGM.getModule(); - auto &Ctx = M->getContext(); + ASTContext &C = getContext(); + QualType QInt64Ty = C.getIntTypeForBitwidth(64, false); + + FunctionArgList FnArgs; + ImplicitParamDecl ArgCallsiteTypeId(C, QInt64Ty, ImplicitParamKind::Other); + ImplicitParamDecl ArgAddr(C, C.VoidPtrTy, ImplicitParamKind::Other); + ImplicitParamDecl ArgCFICheckFailData(C, C.VoidPtrTy, + ImplicitParamKind::Other); + FnArgs.push_back(&ArgCallsiteTypeId); + FnArgs.push_back(&ArgAddr); + FnArgs.push_back(&ArgCFICheckFailData); + const CGFunctionInfo &FI = + CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, FnArgs); + llvm::Function *F = llvm::Function::Create( - llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false), + llvm::FunctionType::get(VoidTy, {Int64Ty, VoidPtrTy, VoidPtrTy}, false), llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false); + CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F); F->setAlignment(llvm::Align(4096)); CGM.setDSOLocal(F); + + llvm::LLVMContext &Ctx = M->getContext(); llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F); // CrossDSOCFI pass is not executed if there is no executable code. SmallVector Args{F->getArg(2), F->getArg(1)}; diff --git a/clang/test/CodeGen/cfi-check-attrs.c b/clang/test/CodeGen/cfi-check-attrs.c new file mode 100644 index 000000000000..375aa30074d8 --- /dev/null +++ b/clang/test/CodeGen/cfi-check-attrs.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple arm-unknown-linux -funwind-tables=1 -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck %s + +// CHECK: define weak {{.*}}void @__cfi_check({{.*}} [[ATTR:#[0-9]*]] + +// CHECK: attributes [[ATTR]] = {{.*}} uwtable(sync) diff --git a/clang/test/CodeGen/cfi-check-fail.c b/clang/test/CodeGen/cfi-check-fail.c index 2f12cee9dec6..15f6c77abf2b 100644 --- a/clang/test/CodeGen/cfi-check-fail.c +++ b/clang/test/CodeGen/cfi-check-fail.c @@ -72,7 +72,7 @@ void caller(void (*f)(void)) { // CHECK: [[CONT5]]: // CHECK: ret void -// CHECK: define weak void @__cfi_check(i64 %[[TYPE:.*]], ptr %[[ADDR:.*]], ptr %[[DATA:.*]]) align 4096 +// CHECK: define weak void @__cfi_check(i64 noundef %[[TYPE:.*]], ptr noundef %[[ADDR:.*]], ptr noundef %[[DATA:.*]]){{.*}} align 4096 // CHECK-NOT: } // CHECK: call void @__cfi_check_fail(ptr %[[DATA]], ptr %[[ADDR]]) // CHECK-NEXT: ret void -- GitLab From d345599c2851c7ef25d2350244cbfe7cfef36386 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Tue, 26 Mar 2024 17:41:46 -0700 Subject: [PATCH 017/541] [GISEL][NFC] Use getElementCount instead of getNumElements in more places These cases in particular are done as a precommit to support legalization, regbank selection, and instruction selection for extends, splat vectors, and integer compares in #85938. --- llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp | 3 ++- llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 2 +- llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 2 +- llvm/lib/CodeGen/MachineVerifier.cpp | 3 ++- llvm/lib/CodeGen/RegisterBankInfo.cpp | 7 ++++--- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp index 4ee1793d33d2..c9ee35373cd4 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -154,7 +154,8 @@ static bool mutationIsSane(const LegalizeRule &Rule, case WidenScalar: { if (OldTy.isVector()) { // Number of elements should not change. - if (!NewTy.isVector() || OldTy.getNumElements() != NewTy.getNumElements()) + if (!NewTy.isVector() || + OldTy.getElementCount() != NewTy.getElementCount()) return false; } else { // Both types must be vectors diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index f2665e25d195..07d4cb5eaa23 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -1160,7 +1160,7 @@ void MachineIRBuilder::validateSelectOp(const LLT ResTy, const LLT TstTy, else assert((TstTy.isScalar() || (TstTy.isVector() && - TstTy.getNumElements() == Op0Ty.getNumElements())) && + TstTy.getElementCount() == Op0Ty.getElementCount())) && "type mismatch"); #endif } diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp index 5caf20add2a1..1602cd99c383 100644 --- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp +++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp @@ -51,7 +51,7 @@ MVT llvm::getMVTForLLT(LLT Ty) { return MVT::getVectorVT( MVT::getIntegerVT(Ty.getElementType().getSizeInBits()), - Ty.getNumElements()); + Ty.getElementCount()); } EVT llvm::getApproximateEVTForLLT(LLT Ty, const DataLayout &DL, diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index 9a1498d4070e..e4e05ce9278c 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1506,7 +1506,8 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { LLT SrcTy = MRI->getType(MI->getOperand(2).getReg()); if ((DstTy.isVector() != SrcTy.isVector()) || - (DstTy.isVector() && DstTy.getNumElements() != SrcTy.getNumElements())) + (DstTy.isVector() && + DstTy.getElementCount() != SrcTy.getElementCount())) report("Generic vector icmp/fcmp must preserve number of lanes", MI); break; diff --git a/llvm/lib/CodeGen/RegisterBankInfo.cpp b/llvm/lib/CodeGen/RegisterBankInfo.cpp index 5548430d1b0a..72b07eb1902d 100644 --- a/llvm/lib/CodeGen/RegisterBankInfo.cpp +++ b/llvm/lib/CodeGen/RegisterBankInfo.cpp @@ -484,9 +484,10 @@ void RegisterBankInfo::applyDefaultMapping(const OperandsMapper &OpdMapper) { // the storage. However, right now we don't necessarily bump all // the types to storage size. For instance, we can consider // s16 G_AND legal whereas the storage size is going to be 32. - assert(OrigTy.getSizeInBits() <= NewTy.getSizeInBits() && - "Types with difference size cannot be handled by the default " - "mapping"); + assert( + TypeSize::isKnownLE(OrigTy.getSizeInBits(), NewTy.getSizeInBits()) && + "Types with difference size cannot be handled by the default " + "mapping"); LLVM_DEBUG(dbgs() << "\nChange type of new opd from " << NewTy << " to " << OrigTy); MRI.setType(NewReg, OrigTy); -- GitLab From d023995ae2cc6ab968ec305ea7b6f11b6ac2e78f Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Tue, 26 Mar 2024 17:51:03 -0700 Subject: [PATCH 018/541] AMDGPU: Simplify EmitAMDGPUBuiltinExpr for load transposes, NFC (#86707) We should not manually get the types of the loading data. Instead, we can get the types from the intrinsics directly. --- clang/lib/CodeGen/CGBuiltin.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 46a815155e7b..3cfdb261a0ea 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -18544,31 +18544,19 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: { Intrinsic::ID IID; - llvm::Type *ArgTy; switch (BuiltinID) { case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32: - ArgTy = llvm::Type::getInt32Ty(getLLVMContext()); - IID = Intrinsic::amdgcn_global_load_tr_b64; - break; case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt32Ty(getLLVMContext()), 2); IID = Intrinsic::amdgcn_global_load_tr_b64; break; case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt16Ty(getLLVMContext()), 4); - IID = Intrinsic::amdgcn_global_load_tr_b128; - break; case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt16Ty(getLLVMContext()), 8); IID = Intrinsic::amdgcn_global_load_tr_b128; break; } - + llvm::Type *LoadTy = ConvertType(E->getType()); llvm::Value *Addr = EmitScalarExpr(E->getArg(0)); - llvm::Function *F = CGM.getIntrinsic(IID, {ArgTy}); + llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy}); return Builder.CreateCall(F, {Addr}); } case AMDGPU::BI__builtin_amdgcn_get_fpenv: { -- GitLab From 4720e3831b814fdd2e8441ee0ac05b6934fdf533 Mon Sep 17 00:00:00 2001 From: Enna1 Date: Wed, 27 Mar 2024 09:06:45 +0800 Subject: [PATCH 019/541] [NFC][Sanitizer] Refine the restriction on SizeClassAllocator64::kRegionSize (#86270) This patch replaces the `SANITIZER_WORDSIZE / 2` with `sizeof(CompactPtrT) * 8`, replaces hardcoded `4` with `kCompactPtrScale` in assertion. --- .../lib/sanitizer_common/sanitizer_allocator_primary64.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h index 34a64f26478f..6e73065d7f53 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h @@ -639,7 +639,8 @@ class SizeClassAllocator64 { static_assert(kRegionSize >= SizeClassMap::kMaxSize, "Region size exceed largest size"); // kRegionSize must be <= 2^36, see CompactPtrT. - COMPILER_CHECK((kRegionSize) <= (1ULL << (SANITIZER_WORDSIZE / 2 + 4))); + COMPILER_CHECK((kRegionSize) <= + (1ULL << (sizeof(CompactPtrT) * 8 + kCompactPtrScale))); // Call mmap for user memory with at least this size. static const uptr kUserMapSize = 1 << 18; // Call mmap for metadata memory with at least this size. -- GitLab From 10b07f2324aa990664c4141ffab534603af35c7a Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Wed, 27 Mar 2024 10:49:24 +0900 Subject: [PATCH 020/541] [mlir][Interfaces] `ValueBoundsConstraintSet`: Add `dump` helper function (#86634) This commit adds a helper function that dumps the constraint set and the mapping of columns to values/dims. For debugging only. Example output: ``` ========== Columns: (column dim value) 0 1 linalg.fill (result 0) 1 1 tensor.extract_slice (result 0) 2 n/a affine.min (result 0) 3 n/a scf.for (bbarg 0) 4 n/a func.func (bbarg 2) Constraint set: Domain: 0, Range: 1, Symbols: 4, Locals: 0 6 constraints (None None None None None const) 1 -1 0 0 0 0 = 0 0 1 -1 0 0 0 = 0 0 0 -1 -1 1 0 >= 0 0 0 -1 0 0 4 >= 0 0 0 0 1 0 0 >= 0 0 0 0 -1 1 -1 >= 0 ========== ``` --- .../mlir/Interfaces/ValueBoundsOpInterface.h | 4 +++ .../lib/Interfaces/ValueBoundsOpInterface.cpp | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h b/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h index b4ed0967e63f..bdfd689c7ac4 100644 --- a/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h +++ b/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h @@ -259,6 +259,10 @@ public: /// Return an expression that represents a constant. AffineExpr getExpr(int64_t constant); + /// Debugging only: Dump the constraint set and the column-to-value/dim + /// mapping to llvm::errs. + void dump() const; + protected: /// Dimension identifier to indicate a value is index-typed. This is used for /// internal data structures/API only. diff --git a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp index 06ec3f4e135e..99598f2e89d9 100644 --- a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp +++ b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp @@ -715,6 +715,35 @@ ValueBoundsConstraintSet::areEquivalentSlices(MLIRContext *ctx, return true; } +void ValueBoundsConstraintSet::dump() const { + llvm::errs() << "==========\nColumns:\n"; + llvm::errs() << "(column\tdim\tvalue)\n"; + for (auto [index, valueDim] : llvm::enumerate(positionToValueDim)) { + llvm::errs() << " " << index << "\t"; + if (valueDim) { + if (valueDim->second == kIndexValue) { + llvm::errs() << "n/a\t"; + } else { + llvm::errs() << valueDim->second << "\t"; + } + llvm::errs() << getOwnerOfValue(valueDim->first)->getName() << " "; + if (OpResult result = dyn_cast(valueDim->first)) { + llvm::errs() << "(result " << result.getResultNumber() << ")"; + } else { + llvm::errs() << "(bbarg " + << cast(valueDim->first).getArgNumber() + << ")"; + } + llvm::errs() << "\n"; + } else { + llvm::errs() << "n/a\tn/a\n"; + } + } + llvm::errs() << "\nConstraint set:\n"; + cstr.dump(); + llvm::errs() << "==========\n"; +} + ValueBoundsConstraintSet::BoundBuilder & ValueBoundsConstraintSet::BoundBuilder::operator[](int64_t dim) { assert(!this->dim.has_value() && "dim was already set"); -- GitLab From fa1b807befdc7b31b1c0e0ab625170924f7b4951 Mon Sep 17 00:00:00 2001 From: "Oleksandr \"Alex\" Zinenko" Date: Wed, 27 Mar 2024 02:58:06 +0100 Subject: [PATCH 021/541] [mlir] fix crash in transform.print verification (#86679) Transform op trait verification calls `getEffects`, and since trait verification runs before op verification, this call cannot assume the op to be valid. However, the operand getters now return a `TypedValue` that unconditionally casts the value to the expected type, leading to an assertion failure. Use the untyped mechanism instead. Fixes #84701. --- mlir/lib/Dialect/Transform/IR/TransformOps.cpp | 6 +++++- mlir/test/Dialect/Transform/ops-invalid.mlir | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp index 8d2ed8f6d737..abd557a508a1 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp @@ -2628,7 +2628,11 @@ transform::PrintOp::apply(transform::TransformRewriter &rewriter, void transform::PrintOp::getEffects( SmallVectorImpl &effects) { - onlyReadsHandle(getTarget(), effects); + // We don't really care about mutability here, but `getTarget` now + // unconditionally casts to a specific type before verification could run + // here. + if (!getTargetMutable().empty()) + onlyReadsHandle(getTargetMutable()[0].get(), effects); onlyReadsPayload(effects); // There is no resource for stderr file descriptor, so just declare print diff --git a/mlir/test/Dialect/Transform/ops-invalid.mlir b/mlir/test/Dialect/Transform/ops-invalid.mlir index 73a5f36af929..cc04e65420c5 100644 --- a/mlir/test/Dialect/Transform/ops-invalid.mlir +++ b/mlir/test/Dialect/Transform/ops-invalid.mlir @@ -771,3 +771,14 @@ module attributes { transform.with_named_sequence } { transform.yield %arg0 : !transform.any_op } } + +// ----- + +module attributes { transform.with_named_sequence } { + transform.named_sequence @match_matmul(%entry: !transform.any_op) -> () { + %c3 = transform.param.constant 1 : i64 -> !transform.param + // expected-error @below {{op operand #0 must be TransformHandleTypeInterface instance}} + transform.print %c3 : !transform.param + transform.yield + } +} -- GitLab From 7545c635729a2055a429c5decd26a619a8d6e74b Mon Sep 17 00:00:00 2001 From: Shih-Po Hung Date: Wed, 27 Mar 2024 10:58:17 +0800 Subject: [PATCH 022/541] [RISCV][TTI] Scale the cost of the sext/zext with LMUL (#86617) Use the destination data type to measure the LMUL size for latency/throughput cost --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 20 +- llvm/test/Analysis/CostModel/RISCV/cast.ll | 920 +++++++++--------- .../CostModel/RISCV/reduce-scalable-int.ll | 12 +- .../CostModel/RISCV/rvv-extractelement.ll | 84 +- .../CostModel/RISCV/rvv-insertelement.ll | 84 +- .../CostModel/RISCV/shuffle-broadcast.ll | 2 +- 6 files changed, 566 insertions(+), 556 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index df289be18932..a0652d41e9f2 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -909,23 +909,33 @@ InstructionCost RISCVTTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, if (!IsTypeLegal) return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + std::pair DstLT = getTypeLegalizationCost(Dst); + int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); - // FIXME: Need to consider vsetvli and lmul. int PowDiff = (int)Log2_32(Dst->getScalarSizeInBits()) - (int)Log2_32(Src->getScalarSizeInBits()); switch (ISD) { case ISD::SIGN_EXTEND: - case ISD::ZERO_EXTEND: - if (Src->getScalarSizeInBits() == 1) { + case ISD::ZERO_EXTEND: { + const unsigned SrcEltSize = Src->getScalarSizeInBits(); + if (SrcEltSize == 1) { // We do not use vsext/vzext to extend from mask vector. // Instead we use the following instructions to extend from mask vector: // vmv.v.i v8, 0 // vmerge.vim v8, v8, -1, v0 - return 2; + return getRISCVInstructionCost({RISCV::VMV_V_I, RISCV::VMERGE_VIM}, + DstLT.second, CostKind); } - return 1; + if (PowDiff > 3) + return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + unsigned SExtOp[] = {RISCV::VSEXT_VF2, RISCV::VSEXT_VF4, RISCV::VSEXT_VF8}; + unsigned ZExtOp[] = {RISCV::VZEXT_VF2, RISCV::VZEXT_VF4, RISCV::VZEXT_VF8}; + unsigned Op = + (ISD == ISD::SIGN_EXTEND) ? SExtOp[PowDiff - 1] : ZExtOp[PowDiff - 1]; + return getRISCVInstructionCost(Op, DstLT.second, CostKind); + } case ISD::TRUNCATE: if (Dst->getScalarSizeInBits() == 1) { // We do not use several vncvt to truncate to mask vector. So we could diff --git a/llvm/test/Analysis/CostModel/RISCV/cast.ll b/llvm/test/Analysis/CostModel/RISCV/cast.ll index bd26c19c2f2c..14da9a3f79d7 100644 --- a/llvm/test/Analysis/CostModel/RISCV/cast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/cast.ll @@ -16,74 +16,74 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext undef to @@ -96,73 +96,73 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -179,74 +179,74 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext undef to @@ -259,73 +259,73 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -522,74 +522,74 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext undef to @@ -602,73 +602,73 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -685,74 +685,74 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext undef to @@ -765,73 +765,73 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll index 80efe912c869..30cb32ce4eaf 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll @@ -1141,7 +1141,7 @@ define signext i32 @vreduce_add_nxv4i32( %v) { define signext i32 @vwreduce_add_nxv4i16( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1157,7 +1157,7 @@ define signext i32 @vwreduce_add_nxv4i16( %v) { define signext i32 @vwreduce_uadd_nxv4i16( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1445,7 +1445,7 @@ define i64 @vreduce_add_nxv2i64( %v) { define i64 @vwreduce_add_nxv2i32( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1461,7 +1461,7 @@ define i64 @vwreduce_add_nxv2i32( %v) { define i64 @vwreduce_uadd_nxv2i32( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1597,7 +1597,7 @@ define i64 @vreduce_add_nxv4i64( %v) { define i64 @vwreduce_add_nxv4i32( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1613,7 +1613,7 @@ define i64 @vwreduce_add_nxv4i32( %v) { define i64 @vwreduce_uadd_nxv4i32( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll index 225bad6da591..aa7a90bece33 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll @@ -12,12 +12,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -66,12 +66,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -120,12 +120,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -177,12 +177,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -231,12 +231,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -285,12 +285,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -341,13 +341,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -395,13 +395,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -449,13 +449,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -506,13 +506,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -560,13 +560,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -614,13 +614,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll index 5387c8dc3594..6e1ae0216f76 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll @@ -12,12 +12,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -66,12 +66,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -120,12 +120,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -177,12 +177,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -231,12 +231,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -285,12 +285,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -341,13 +341,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -395,13 +395,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -449,13 +449,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -506,13 +506,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -560,13 +560,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -614,13 +614,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll index 46bf3152ac5b..b763198e98ba 100644 --- a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll @@ -197,7 +197,7 @@ define void @broadcast_fixed() #0{ ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %41 = shufflevector <32 x i1> undef, <32 x i1> undef, <32 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %42 = shufflevector <64 x i1> undef, <64 x i1> undef, <64 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %43 = shufflevector <128 x i1> undef, <128 x i1> undef, <128 x i32> zeroinitializer -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %44 = shufflevector <128 x i1> %ins1, <128 x i1> poison, <128 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ins2 = insertelement <2 x i8> poison, i8 3, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %45 = shufflevector <2 x i8> %ins2, <2 x i8> undef, <2 x i32> zeroinitializer -- GitLab From 082e7c480e033c1b973b8379a31929d04e236868 Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Tue, 26 Mar 2024 20:06:27 -0700 Subject: [PATCH 023/541] [MemProf] Remove empty edges once after cloning (#85320) Restructure the handling of edges that become empty during the cloning process. Instead of removing them as they become empty (no context ids and alloc type), do this once after all cloning is complete. This has no effect on the cloning result, but prepares for a follow on change that does improve the cloning. The structural change here reduces the diffs for the follow on change, which would be much more difficult with the previous handling. --- .../IPO/MemProfContextDisambiguation.cpp | 84 ++++++++++++------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp index ba5e3b637db7..4e4a49997766 100644 --- a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp +++ b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp @@ -310,8 +310,12 @@ public: // True if this node was effectively removed from the graph, in which case // its context id set, caller edges, and callee edges should all be empty. bool isRemoved() const { - assert(ContextIds.empty() == - (CalleeEdges.empty() && CallerEdges.empty())); + // Note that we can have non-empty context ids with empty caller and + // callee edges if the graph ends up with a single node. + if (ContextIds.empty()) + assert(CalleeEdges.empty() && CallerEdges.empty() && + "Context ids empty but at least one of callee and caller edges " + "were not!"); return ContextIds.empty(); } @@ -353,9 +357,12 @@ public: } }; - /// Helper to remove callee edges that have allocation type None (due to not + /// Helpers to remove callee edges that have allocation type None (due to not /// carrying any context ids) after transformations. void removeNoneTypeCalleeEdges(ContextNode *Node); + void + recursivelyRemoveNoneTypeCalleeEdges(ContextNode *Node, + DenseSet &Visited); protected: /// Get a list of nodes corresponding to the stack ids in the given callsite @@ -2431,11 +2438,43 @@ void CallsiteContextGraph:: } } +template +void CallsiteContextGraph:: + recursivelyRemoveNoneTypeCalleeEdges( + ContextNode *Node, DenseSet &Visited) { + auto Inserted = Visited.insert(Node); + if (!Inserted.second) + return; + + removeNoneTypeCalleeEdges(Node); + + for (auto *Clone : Node->Clones) + recursivelyRemoveNoneTypeCalleeEdges(Clone, Visited); + + // The recursive call may remove some of this Node's caller edges. + // Iterate over a copy and skip any that were removed. + auto CallerEdges = Node->CallerEdges; + for (auto &Edge : CallerEdges) { + // Skip any that have been removed by an earlier recursive call. + if (Edge->Callee == nullptr && Edge->Caller == nullptr) { + assert(!std::count(Node->CallerEdges.begin(), Node->CallerEdges.end(), + Edge)); + continue; + } + recursivelyRemoveNoneTypeCalleeEdges(Edge->Caller, Visited); + } +} + template void CallsiteContextGraph::identifyClones() { DenseSet Visited; for (auto &Entry : AllocationCallToContextNodeMap) identifyClones(Entry.second, Visited); + Visited.clear(); + for (auto &Entry : AllocationCallToContextNodeMap) + recursivelyRemoveNoneTypeCalleeEdges(Entry.second, Visited); + if (VerifyCCG) + check(); } // helper function to check an AllocType is cold or notcold or both. @@ -2450,7 +2489,7 @@ template void CallsiteContextGraph::identifyClones( ContextNode *Node, DenseSet &Visited) { if (VerifyNodes) - checkNode(Node); + checkNode(Node, /*CheckEdges=*/false); assert(!Node->CloneOf); // If Node as a null call, then either it wasn't found in the module (regular @@ -2511,8 +2550,16 @@ void CallsiteContextGraph::identifyClones( std::stable_sort(Node->CallerEdges.begin(), Node->CallerEdges.end(), [&](const std::shared_ptr &A, const std::shared_ptr &B) { - assert(checkColdOrNotCold(A->AllocTypes) && - checkColdOrNotCold(B->AllocTypes)); + // Nodes with non-empty context ids should be sorted before + // those with empty context ids. + if (A->ContextIds.empty()) + // Either B ContextIds are non-empty (in which case we + // should return false because B < A), or B ContextIds + // are empty, in which case they are equal, and we should + // maintain the original relative ordering. + return false; + if (B->ContextIds.empty()) + return true; if (A->AllocTypes == B->AllocTypes) // Use the first context id for each edge as a @@ -2591,39 +2638,16 @@ void CallsiteContextGraph::identifyClones( Node->AllocTypes != (uint8_t)AllocationType::None); // Sanity check that no alloc types on clone or its edges are None. assert(Clone->AllocTypes != (uint8_t)AllocationType::None); - assert(llvm::none_of( - Clone->CallerEdges, [&](const std::shared_ptr &E) { - return E->AllocTypes == (uint8_t)AllocationType::None; - })); } - // Cloning may have resulted in some cloned callee edges with type None, - // because they aren't carrying any contexts. Remove those edges. - for (auto *Clone : Node->Clones) { - removeNoneTypeCalleeEdges(Clone); - if (VerifyNodes) - checkNode(Clone); - } // We should still have some context ids on the original Node. assert(!Node->ContextIds.empty()); - // Remove any callee edges that ended up with alloc type None after creating - // clones and updating callee edges. - removeNoneTypeCalleeEdges(Node); - // Sanity check that no alloc types on node or edges are None. assert(Node->AllocTypes != (uint8_t)AllocationType::None); - assert(llvm::none_of(Node->CalleeEdges, - [&](const std::shared_ptr &E) { - return E->AllocTypes == (uint8_t)AllocationType::None; - })); - assert(llvm::none_of(Node->CallerEdges, - [&](const std::shared_ptr &E) { - return E->AllocTypes == (uint8_t)AllocationType::None; - })); if (VerifyNodes) - checkNode(Node); + checkNode(Node, /*CheckEdges=*/false); } void ModuleCallsiteContextGraph::updateAllocationCall( -- GitLab From 4d03a9ecc697a11f0edd3c31440a7cae3398e24a Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 26 Mar 2024 20:42:14 -0700 Subject: [PATCH 024/541] [RISCV] Preserve MMO when expanding PseudoRV32ZdinxSD/PseudoRV32ZdinxLD. (#85877) This allows the asm printer to print the stack spill/reload messages. --- .../Target/RISCV/RISCVExpandPseudoInsts.cpp | 35 +++++++++++++++---- llvm/test/CodeGen/RISCV/zdinx-large-spill.mir | 32 ++++++++--------- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp index 0a314fdd41cb..173995f05b51 100644 --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -312,10 +312,19 @@ bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB, TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even); Register Hi = TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd); + + assert(MBBI->hasOneMemOperand() && "Expected mem operand"); + MachineMemOperand *OldMMO = MBBI->memoperands().front(); + MachineFunction *MF = MBB.getParent(); + MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4); + MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4); + BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill())) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOLo); + if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) { // FIXME: Zdinx RV32 can not work on unaligned memory. assert(!STI->hasFastUnalignedAccess()); @@ -325,13 +334,15 @@ bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill())) .add(MBBI->getOperand(1)) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOHi); } else { assert(isInt<12>(MBBI->getOperand(2).getImm() + 4)); BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill())) .add(MBBI->getOperand(1)) - .addImm(MBBI->getOperand(2).getImm() + 4); + .addImm(MBBI->getOperand(2).getImm() + 4) + .setMemRefs(MMOHi); } MBBI->eraseFromParent(); return true; @@ -349,6 +360,12 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, Register Hi = TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd); + assert(MBBI->hasOneMemOperand() && "Expected mem operand"); + MachineMemOperand *OldMMO = MBBI->memoperands().front(); + MachineFunction *MF = MBB.getParent(); + MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4); + MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4); + // If the register of operand 1 is equal to the Lo register, then swap the // order of loading the Lo and Hi statements. bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg(); @@ -356,7 +373,8 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, if (!IsOp1EqualToLo) { BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOLo); } if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) { @@ -365,20 +383,23 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, MBBI->getOperand(2).setOffset(Offset + 4); BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOHi); MBBI->getOperand(2).setOffset(Offset); } else { assert(isInt<12>(MBBI->getOperand(2).getImm() + 4)); BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi) .addReg(MBBI->getOperand(1).getReg()) - .addImm(MBBI->getOperand(2).getImm() + 4); + .addImm(MBBI->getOperand(2).getImm() + 4) + .setMemRefs(MMOHi); } // Order: Hi, Lo if (IsOp1EqualToLo) { BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOLo); } MBBI->eraseFromParent(); diff --git a/llvm/test/CodeGen/RISCV/zdinx-large-spill.mir b/llvm/test/CodeGen/RISCV/zdinx-large-spill.mir index a2a722a7f728..8596a65c378c 100644 --- a/llvm/test/CodeGen/RISCV/zdinx-large-spill.mir +++ b/llvm/test/CodeGen/RISCV/zdinx-large-spill.mir @@ -14,28 +14,28 @@ ; CHECK-NEXT: .cfi_def_cfa_offset 2064 ; CHECK-NEXT: lui t0, 1 ; CHECK-NEXT: add t0, sp, t0 - ; CHECK-NEXT: sw a0, -2040(t0) - ; CHECK-NEXT: sw a1, -2036(t0) + ; CHECK-NEXT: sw a0, -2040(t0) # 4-byte Folded Spill + ; CHECK-NEXT: sw a1, -2036(t0) # 4-byte Folded Spill ; CHECK-NEXT: lui a0, 1 ; CHECK-NEXT: add a0, sp, a0 - ; CHECK-NEXT: sw a2, -2048(a0) - ; CHECK-NEXT: sw a3, -2044(a0) - ; CHECK-NEXT: sw a4, 2040(sp) - ; CHECK-NEXT: sw a5, 2044(sp) - ; CHECK-NEXT: sw a6, 2032(sp) - ; CHECK-NEXT: sw a7, 2036(sp) + ; CHECK-NEXT: sw a2, -2048(a0) # 4-byte Folded Spill + ; CHECK-NEXT: sw a3, -2044(a0) # 4-byte Folded Spill + ; CHECK-NEXT: sw a4, 2040(sp) # 4-byte Folded Spill + ; CHECK-NEXT: sw a5, 2044(sp) # 4-byte Folded Spill + ; CHECK-NEXT: sw a6, 2032(sp) # 4-byte Folded Spill + ; CHECK-NEXT: sw a7, 2036(sp) # 4-byte Folded Spill ; CHECK-NEXT: lui a0, 1 ; CHECK-NEXT: add a0, sp, a0 - ; CHECK-NEXT: lw a1, -2036(a0) - ; CHECK-NEXT: lw a0, -2040(a0) + ; CHECK-NEXT: lw a1, -2036(a0) # 4-byte Folded Reload + ; CHECK-NEXT: lw a0, -2040(a0) # 4-byte Folded Reload ; CHECK-NEXT: lui a0, 1 ; CHECK-NEXT: add a0, sp, a0 - ; CHECK-NEXT: lw a2, -2048(a0) - ; CHECK-NEXT: lw a3, -2044(a0) - ; CHECK-NEXT: lw a4, 2040(sp) - ; CHECK-NEXT: lw a5, 2044(sp) - ; CHECK-NEXT: lw a6, 2032(sp) - ; CHECK-NEXT: lw a7, 2036(sp) + ; CHECK-NEXT: lw a2, -2048(a0) # 4-byte Folded Reload + ; CHECK-NEXT: lw a3, -2044(a0) # 4-byte Folded Reload + ; CHECK-NEXT: lw a4, 2040(sp) # 4-byte Folded Reload + ; CHECK-NEXT: lw a5, 2044(sp) # 4-byte Folded Reload + ; CHECK-NEXT: lw a6, 2032(sp) # 4-byte Folded Reload + ; CHECK-NEXT: lw a7, 2036(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 2032 ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret -- GitLab From 9961c03e9ec2fc47cb42fd16141b89dd8d8e2c01 Mon Sep 17 00:00:00 2001 From: Jeremy Day Date: Tue, 26 Mar 2024 21:03:29 -0700 Subject: [PATCH 025/541] Return `errc::no_such_file_or_directory` in `fs::access` if `GetFileAttributesW` fails (#83495) Fixes https://github.com/llvm/llvm-project/issues/83046 There is a race condition when calling `GetFileAttributesW` that can cause it to return `ERROR_ACCESS_DENIED` on a path which exists, which is unexpected for callers using this function to check for file existence by passing `AccessMode::Exist`. This was manifesting as a compiler crash on Windows downstream in the Swift compiler when using the `-index-store-path` flag (more information in https://github.com/apple/llvm-project/issues/8224). I looked for alternate APIs to avoid bringing in `shlwapi.h`, but didn't see any good candidates. I'm not tied at all to this solution, any feedback and alternative approaches are more than welcome. --- llvm/lib/Support/Windows/Path.inc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index 3e4c1f74161c..854d531ab371 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -623,6 +623,10 @@ std::error_code access(const Twine &Path, AccessMode Mode) { DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin()); if (Attributes == INVALID_FILE_ATTRIBUTES) { + // Avoid returning unexpected error codes when querying for existence. + if (Mode == AccessMode::Exist) + return errc::no_such_file_or_directory; + // See if the file didn't actually exist. DWORD LastError = ::GetLastError(); if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND) -- GitLab From fa9ee4a7f9f7fb9f586d40939269205fc3061c17 Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Wed, 27 Mar 2024 00:09:40 -0400 Subject: [PATCH 026/541] [NFC][OpenMP] Silent unused variable in `kmp_collapse.cpp` --- openmp/runtime/src/kmp_collapse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmp/runtime/src/kmp_collapse.cpp b/openmp/runtime/src/kmp_collapse.cpp index e63a98081db9..f1bf04901dc7 100644 --- a/openmp/runtime/src/kmp_collapse.cpp +++ b/openmp/runtime/src/kmp_collapse.cpp @@ -1482,8 +1482,8 @@ void kmp_handle_upper_triangle_matrix( original_bounds_nest[0].ub0_u64); kmp_uint64 outer_lb0 = kmp_fix_iv(original_bounds_nest[0].loop_iv_type, original_bounds_nest[0].lb0_u64); - kmp_uint64 inner_ub0 = kmp_fix_iv(original_bounds_nest[1].loop_iv_type, - original_bounds_nest[1].ub0_u64); + [[maybe_unused]] kmp_uint64 inner_ub0 = kmp_fix_iv( + original_bounds_nest[1].loop_iv_type, original_bounds_nest[1].ub0_u64); // calculate the chunk's lower and upper bounds // the total number of iterations in the loop is the sum of the arithmetic // progression from the outer lower to outer upper bound (inclusive since the -- GitLab From a7ac0dd624962de1ccb55f1ed1357f548477f593 Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Wed, 27 Mar 2024 00:23:32 -0400 Subject: [PATCH 027/541] [NFC][OpenMP] Use `SimpleVLA` to replace variable length arrays in C++ --- openmp/runtime/src/kmp_csupport.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openmp/runtime/src/kmp_csupport.cpp b/openmp/runtime/src/kmp_csupport.cpp index 878e78b5c7ad..0268f692ff7f 100644 --- a/openmp/runtime/src/kmp_csupport.cpp +++ b/openmp/runtime/src/kmp_csupport.cpp @@ -18,6 +18,7 @@ #include "kmp_itt.h" #include "kmp_lock.h" #include "kmp_stats.h" +#include "kmp_utils.h" #include "ompt-specific.h" #define MAX_MESSAGE 512 @@ -4233,7 +4234,7 @@ void __kmpc_doacross_wait(ident_t *loc, int gtid, const kmp_int64 *vec) { up = pr_buf->th_doacross_info[3]; st = pr_buf->th_doacross_info[4]; #if OMPT_SUPPORT && OMPT_OPTIONAL - ompt_dependence_t deps[num_dims]; + SimpleVLA deps(num_dims); #endif if (st == 1) { // most common case if (vec[0] < lo || vec[0] > up) { @@ -4345,7 +4346,7 @@ void __kmpc_doacross_post(ident_t *loc, int gtid, const kmp_int64 *vec) { lo = pr_buf->th_doacross_info[2]; st = pr_buf->th_doacross_info[4]; #if OMPT_SUPPORT && OMPT_OPTIONAL - ompt_dependence_t deps[num_dims]; + SimpleVLA deps(num_dims); #endif if (st == 1) { // most common case iter_number = vec[0] - lo; -- GitLab From ecf6bb2b4dbd26bbff2cee79db010369faa2fe90 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 26 Mar 2024 21:35:35 -0700 Subject: [PATCH 028/541] [RISCV] Add register overlap checks to the assembler for some Zvk* instructions. (#86745) From the spec | Instruction | Register | Cannot Overlap | | ----------- | -------- | -------------- | | vaes*.vs | vs2 | vd | | vsm4r.vs | vs2 | vd | | vsha2c[hl] | vs1, vs2 | vd | | vsha2ms | vs1, vs2 | vd | | sm3me | vs2 | vd | | vsm3c | vs2 | vd | --- llvm/lib/Target/RISCV/RISCVInstrFormats.td | 2 ++ llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td | 12 ++++++---- llvm/test/MC/RISCV/rvv/zvkned-invalid.s | 23 +++++++++++++++++++ llvm/test/MC/RISCV/rvv/zvknh-invalid.s | 26 ++++++++++++++++++++++ llvm/test/MC/RISCV/rvv/zvksed-invalid.s | 6 +++++ llvm/test/MC/RISCV/rvv/zvksh-invalid.s | 10 +++++++++ llvm/test/MC/RISCV/rvv/zvksh.s | 7 ++++++ 7 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 llvm/test/MC/RISCV/rvv/zvkned-invalid.s create mode 100644 llvm/test/MC/RISCV/rvv/zvknh-invalid.s create mode 100644 llvm/test/MC/RISCV/rvv/zvksed-invalid.s create mode 100644 llvm/test/MC/RISCV/rvv/zvksh-invalid.s diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td index f56f49ae2457..52c794446af0 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td +++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td @@ -109,6 +109,8 @@ def Vrgather : RISCVVConstraint; def Vcompress : RISCVVConstraint; +def Sha2Constraint : RISCVVConstraint; // The following opcode names match those given in Table 19.1 in the // RISC-V User-level ISA specification ("RISC-V base opcode map"). diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td index 035ce63e91e9..b388bb00b0f2 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td @@ -82,7 +82,9 @@ class PALUVs2NoVm funct6, bits<5> vs1, RISCVVFormat opv, string opcodest multiclass VAES_MV_V_S funct6_vv, bits<6> funct6_vs, bits<5> vs1, RISCVVFormat opv, string opcodestr> { + let RVVConstraint = NoConstraint in def NAME # _VV : PALUVs2NoVm; + let RVVConstraint = VS2Constraint in def NAME # _VS : PALUVs2NoVm; } } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 @@ -118,28 +120,30 @@ let Predicates = [HasStdExtZvkg], RVVConstraint = NoConstraint in { def VGMUL_VV : PALUVs2NoVm<0b101000, 0b10001, OPMVV, "vgmul.vv">; } // Predicates = [HasStdExtZvkg] -let Predicates = [HasStdExtZvknhaOrZvknhb], RVVConstraint = NoConstraint in { +let Predicates = [HasStdExtZvknhaOrZvknhb], RVVConstraint = Sha2Constraint in { def VSHA2CH_VV : PALUVVNoVm<0b101110, OPMVV, "vsha2ch.vv">; def VSHA2CL_VV : PALUVVNoVm<0b101111, OPMVV, "vsha2cl.vv">; def VSHA2MS_VV : PALUVVNoVm<0b101101, OPMVV, "vsha2ms.vv">; } // Predicates = [HasStdExtZvknhaOrZvknhb] -let Predicates = [HasStdExtZvkned], RVVConstraint = NoConstraint in { +let Predicates = [HasStdExtZvkned]in { defm VAESDF : VAES_MV_V_S<0b101000, 0b101001, 0b00001, OPMVV, "vaesdf">; defm VAESDM : VAES_MV_V_S<0b101000, 0b101001, 0b00000, OPMVV, "vaesdm">; defm VAESEF : VAES_MV_V_S<0b101000, 0b101001, 0b00011, OPMVV, "vaesef">; defm VAESEM : VAES_MV_V_S<0b101000, 0b101001, 0b00010, OPMVV, "vaesem">; def VAESKF1_VI : PALUVINoVm<0b100010, "vaeskf1.vi", uimm5>; def VAESKF2_VI : PALUVINoVm<0b101010, "vaeskf2.vi", uimm5>; + let RVVConstraint = VS2Constraint in def VAESZ_VS : PALUVs2NoVm<0b101001, 0b00111, OPMVV, "vaesz.vs">; } // Predicates = [HasStdExtZvkned] -let Predicates = [HasStdExtZvksed], RVVConstraint = NoConstraint in { +let Predicates = [HasStdExtZvksed] in { + let RVVConstraint = NoConstraint in def VSM4K_VI : PALUVINoVm<0b100001, "vsm4k.vi", uimm5>; defm VSM4R : VAES_MV_V_S<0b101000, 0b101001, 0b10000, OPMVV, "vsm4r">; } // Predicates = [HasStdExtZvksed] -let Predicates = [HasStdExtZvksh], RVVConstraint = NoConstraint in { +let Predicates = [HasStdExtZvksh], RVVConstraint = VS2Constraint in { def VSM3C_VI : PALUVINoVm<0b101011, "vsm3c.vi", uimm5>; def VSM3ME_VV : PALUVVNoVm<0b100000, OPMVV, "vsm3me.vv">; } // Predicates = [HasStdExtZvksh] diff --git a/llvm/test/MC/RISCV/rvv/zvkned-invalid.s b/llvm/test/MC/RISCV/rvv/zvkned-invalid.s new file mode 100644 index 000000000000..9230bc08e3fa --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvkned-invalid.s @@ -0,0 +1,23 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvkned %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vaesdf.vs v10, v10 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesdf.vs v10, v10 + +vaesef.vs v11, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesef.vs v11, v11 + +vaesdm.vs v12, v12 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesdm.vs v12, v12 + +vaesem.vs v13, v13 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesem.vs v13, v13 + +vaesz.vs v14, v14 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesz.vs v14, v14 + diff --git a/llvm/test/MC/RISCV/rvv/zvknh-invalid.s b/llvm/test/MC/RISCV/rvv/zvknh-invalid.s new file mode 100644 index 000000000000..d9902511c0e1 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvknh-invalid.s @@ -0,0 +1,26 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvknha %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vsha2ms.vv v10, v10, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ms.vv v10, v10, v11 + +vsha2ms.vv v11, v10, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ms.vv v11, v10, v11 + +vsha2ch.vv v12, v12, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ch.vv v12, v12, v11 + +vsha2ch.vv v11, v12, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ch.vv v11, v12, v11 + +vsha2cl.vv v13, v13, v15 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2cl.vv v13, v13, v15 + +vsha2cl.vv v15, v13, v15 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2cl.vv v15, v13, v15 diff --git a/llvm/test/MC/RISCV/rvv/zvksed-invalid.s b/llvm/test/MC/RISCV/rvv/zvksed-invalid.s new file mode 100644 index 000000000000..41df8d3bc296 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvksed-invalid.s @@ -0,0 +1,6 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvksed %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vsm4r.vs v10, v10 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsm4r.vs v10, v10 diff --git a/llvm/test/MC/RISCV/rvv/zvksh-invalid.s b/llvm/test/MC/RISCV/rvv/zvksh-invalid.s new file mode 100644 index 000000000000..cccec44b8191 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvksh-invalid.s @@ -0,0 +1,10 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvksh %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vsm3me.vv v10, v10, v8 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsm3me.vv v10, v10, v8 + +vsm3c.vi v9, v9, 7 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsm3c.vi v9, v9, 7 diff --git a/llvm/test/MC/RISCV/rvv/zvksh.s b/llvm/test/MC/RISCV/rvv/zvksh.s index ca6cb49d3079..06251ff6efe5 100644 --- a/llvm/test/MC/RISCV/rvv/zvksh.s +++ b/llvm/test/MC/RISCV/rvv/zvksh.s @@ -19,3 +19,10 @@ vsm3me.vv v10, v9, v8 # CHECK-ENCODING: [0x77,0x25,0x94,0x82] # CHECK-ERROR: instruction requires the following: 'Zvksh' (SM3 Hash Function Instructions){{$}} # CHECK-UNKNOWN: 77 25 94 82 + +# vs1 is allowed to overlap, but not vs2. +vsm3me.vv v10, v9, v10 +# CHECK-INST: vsm3me.vv v10, v9, v10 +# CHECK-ENCODING: [0x77,0x25,0x95,0x82] +# CHECK-ERROR: instruction requires the following: 'Zvksh' (SM3 Hash Function Instructions){{$}} +# CHECK-UNKNOWN: 77 25 95 82 -- GitLab From 8a9c1701704182d551bf9df1ff43363db56caab4 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 26 Mar 2024 21:37:19 -0700 Subject: [PATCH 029/541] [RISCV] Align stack size down to a multiple of 16 before using cm.push/pop. (#86073) This an alternative to #84935 to fix the miscompile, but not be optimal. The immediate for cm.push/pop must be a multiple of 16. For RVE, it might not be. It's not easy to increase the stack size without messing up cfa directives and maybe other things. This patch rounds the stack size down to a multiple of 16 before clamping it to 48. This causes an extra addi to be emitted to handle the remainder. Once this commited, I can commit #84989 to add verification for these instructions being generated with valid offsets. --- llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 12 ++++++++---- llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 8bac41372b5a..39f2b3f62a9a 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -554,8 +554,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, if (RVFI->isPushable(MF) && FirstFrameSetup != MBB.end() && FirstFrameSetup->getOpcode() == RISCV::CM_PUSH) { // Use available stack adjustment in push instruction to allocate additional - // stack space. - uint64_t Spimm = std::min(StackSize, (uint64_t)48); + // stack space. Align the stack size down to a multiple of 16. This is + // needed for RVE. + // FIXME: Can we increase the stack size to a multiple of 16 instead? + uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48); FirstFrameSetup->getOperand(1).setImm(Spimm); StackSize -= Spimm; } @@ -776,8 +778,10 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, if (RVFI->isPushable(MF) && MBBI != MBB.end() && MBBI->getOpcode() == RISCV::CM_POP) { // Use available stack adjustment in pop instruction to deallocate stack - // space. - uint64_t Spimm = std::min(StackSize, (uint64_t)48); + // space. Align the stack size down to a multiple of 16. This is needed for + // RVE. + // FIXME: Can we increase the stack size to a multiple of 16 instead? + uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48); MBBI->getOperand(1).setImm(Spimm); StackSize -= Spimm; } diff --git a/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll b/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll index e5c2e0180ee0..73ace2033985 100644 --- a/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll +++ b/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll @@ -3,7 +3,8 @@ define ptr @func(ptr %s, i32 %_c, ptr %incdec.ptr, i1 %0, i8 %conv14) #0 { ; RV32-LABEL: func: ; RV32: # %bb.0: # %entry -; RV32-NEXT: cm.push {ra, s0-s1}, -24 +; RV32-NEXT: cm.push {ra, s0-s1}, -16 +; RV32-NEXT: addi sp, sp, -8 ; RV32-NEXT: .cfi_def_cfa_offset 24 ; RV32-NEXT: .cfi_offset ra, -12 ; RV32-NEXT: .cfi_offset s0, -8 @@ -31,7 +32,8 @@ define ptr @func(ptr %s, i32 %_c, ptr %incdec.ptr, i1 %0, i8 %conv14) #0 { ; RV32-NEXT: lw a0, 4(sp) # 4-byte Folded Reload ; RV32-NEXT: sb a0, 0(s0) ; RV32-NEXT: mv a0, s1 -; RV32-NEXT: cm.popret {ra, s0-s1}, 24 +; RV32-NEXT: addi sp, sp, 8 +; RV32-NEXT: cm.popret {ra, s0-s1}, 16 entry: br label %while.body -- GitLab From da3e58e74ad160c3dfa89e92f7dd31efeee6b258 Mon Sep 17 00:00:00 2001 From: ShihPo Hung Date: Tue, 26 Mar 2024 21:46:37 -0700 Subject: [PATCH 030/541] Revert "[RISCV][TTI] Scale the cost of the sext/zext with LMUL (#86617)" This reverts commit 7545c635729a2055a429c5decd26a619a8d6e74b as it's failing on the Linux bots. --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 20 +- llvm/test/Analysis/CostModel/RISCV/cast.ll | 920 +++++++++--------- .../CostModel/RISCV/reduce-scalable-int.ll | 12 +- .../CostModel/RISCV/rvv-extractelement.ll | 84 +- .../CostModel/RISCV/rvv-insertelement.ll | 84 +- .../CostModel/RISCV/shuffle-broadcast.ll | 2 +- 6 files changed, 556 insertions(+), 566 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index a0652d41e9f2..df289be18932 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -909,33 +909,23 @@ InstructionCost RISCVTTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, if (!IsTypeLegal) return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); - std::pair DstLT = getTypeLegalizationCost(Dst); - int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); + // FIXME: Need to consider vsetvli and lmul. int PowDiff = (int)Log2_32(Dst->getScalarSizeInBits()) - (int)Log2_32(Src->getScalarSizeInBits()); switch (ISD) { case ISD::SIGN_EXTEND: - case ISD::ZERO_EXTEND: { - const unsigned SrcEltSize = Src->getScalarSizeInBits(); - if (SrcEltSize == 1) { + case ISD::ZERO_EXTEND: + if (Src->getScalarSizeInBits() == 1) { // We do not use vsext/vzext to extend from mask vector. // Instead we use the following instructions to extend from mask vector: // vmv.v.i v8, 0 // vmerge.vim v8, v8, -1, v0 - return getRISCVInstructionCost({RISCV::VMV_V_I, RISCV::VMERGE_VIM}, - DstLT.second, CostKind); + return 2; } - if (PowDiff > 3) - return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); - unsigned SExtOp[] = {RISCV::VSEXT_VF2, RISCV::VSEXT_VF4, RISCV::VSEXT_VF8}; - unsigned ZExtOp[] = {RISCV::VZEXT_VF2, RISCV::VZEXT_VF4, RISCV::VZEXT_VF8}; - unsigned Op = - (ISD == ISD::SIGN_EXTEND) ? SExtOp[PowDiff - 1] : ZExtOp[PowDiff - 1]; - return getRISCVInstructionCost(Op, DstLT.second, CostKind); - } + return 1; case ISD::TRUNCATE: if (Dst->getScalarSizeInBits() == 1) { // We do not use several vncvt to truncate to mask vector. So we could diff --git a/llvm/test/Analysis/CostModel/RISCV/cast.ll b/llvm/test/Analysis/CostModel/RISCV/cast.ll index 14da9a3f79d7..bd26c19c2f2c 100644 --- a/llvm/test/Analysis/CostModel/RISCV/cast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/cast.ll @@ -16,74 +16,74 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext undef to @@ -96,73 +96,73 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -179,74 +179,74 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext undef to @@ -259,73 +259,73 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -522,74 +522,74 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext undef to @@ -602,73 +602,73 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -685,74 +685,74 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext undef to @@ -765,73 +765,73 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll index 30cb32ce4eaf..80efe912c869 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll @@ -1141,7 +1141,7 @@ define signext i32 @vreduce_add_nxv4i32( %v) { define signext i32 @vwreduce_add_nxv4i16( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1157,7 +1157,7 @@ define signext i32 @vwreduce_add_nxv4i16( %v) { define signext i32 @vwreduce_uadd_nxv4i16( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1445,7 +1445,7 @@ define i64 @vreduce_add_nxv2i64( %v) { define i64 @vwreduce_add_nxv2i32( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1461,7 +1461,7 @@ define i64 @vwreduce_add_nxv2i32( %v) { define i64 @vwreduce_uadd_nxv2i32( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1597,7 +1597,7 @@ define i64 @vreduce_add_nxv4i64( %v) { define i64 @vwreduce_add_nxv4i32( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1613,7 +1613,7 @@ define i64 @vwreduce_add_nxv4i32( %v) { define i64 @vwreduce_uadd_nxv4i32( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll index aa7a90bece33..225bad6da591 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll @@ -12,12 +12,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -66,12 +66,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -120,12 +120,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -177,12 +177,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -231,12 +231,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -285,12 +285,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -341,13 +341,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -395,13 +395,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -449,13 +449,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -506,13 +506,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -560,13 +560,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -614,13 +614,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll index 6e1ae0216f76..5387c8dc3594 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll @@ -12,12 +12,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -66,12 +66,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -120,12 +120,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -177,12 +177,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -231,12 +231,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -285,12 +285,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -341,13 +341,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -395,13 +395,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -449,13 +449,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -506,13 +506,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -560,13 +560,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -614,13 +614,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll index b763198e98ba..46bf3152ac5b 100644 --- a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll @@ -197,7 +197,7 @@ define void @broadcast_fixed() #0{ ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %41 = shufflevector <32 x i1> undef, <32 x i1> undef, <32 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %42 = shufflevector <64 x i1> undef, <64 x i1> undef, <64 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %43 = shufflevector <128 x i1> undef, <128 x i1> undef, <128 x i32> zeroinitializer -; CHECK-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %44 = shufflevector <128 x i1> %ins1, <128 x i1> poison, <128 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ins2 = insertelement <2 x i8> poison, i8 3, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %45 = shufflevector <2 x i8> %ins2, <2 x i8> undef, <2 x i32> zeroinitializer -- GitLab From f1dff836593d4601e3ad78117df1d980d284bb9c Mon Sep 17 00:00:00 2001 From: Christian Sigg Date: Wed, 27 Mar 2024 06:07:58 +0100 Subject: [PATCH 031/541] [mlir][bazel] Expose GPUCommonPass.h only by a single target. (#86730) Move `GPUOpsLowering.cpp` from `//mlir:GPUCommonTransforms` to `//mlir:GPUToGPURuntimeTransforms` to match the CMake setup. Ideally, header files should be used by only one target, but this is hard because CMake is less strict with headers (no layering check). But even with bazel, headers should only be exported once in the `hdrs` attribute. Other targets may use them in the `srcs` attribute to avoid circular dependencies. --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 5dcaf0265c92..73556060983b 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -3567,6 +3567,7 @@ cc_library( ":GPUCommonTransforms", ":GPUCompilationAttrInterfacesIncGen", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":IR", ":LLVMCommonConversion", ":LinalgDialect", @@ -5603,6 +5604,7 @@ cc_library( ":FuncToLLVM", ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToNVVMTransforms", ":GPUTransforms", ":IndexToLLVM", @@ -5727,6 +5729,7 @@ cc_library( ":FuncDialect", ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToNVVMTransforms", ":GPUTransformOpsIncGen", ":GPUTransforms", @@ -5774,11 +5777,7 @@ td_library( cc_library( name = "GPUCommonTransforms", - srcs = [ - "lib/Conversion/GPUCommon/GPUOpsLowering.cpp", - ], hdrs = [ - "include/mlir/Conversion/GPUCommon/GPUCommonPass.h", "lib/Conversion/GPUCommon/GPUOpsLowering.h", "lib/Conversion/GPUCommon/IndexIntrinsicsOpLowering.h", "lib/Conversion/GPUCommon/OpToFuncCallLowering.h", @@ -5832,6 +5831,7 @@ cc_library( ":FuncToLLVM", ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToNVVMGen", ":GPUTransforms", ":IR", @@ -5958,6 +5958,7 @@ cc_library( ":FuncToLLVM", ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToROCDLTGen", ":GPUTransforms", ":IR", @@ -6001,6 +6002,7 @@ cc_library( cc_library( name = "GPUToGPURuntimeTransforms", srcs = [ + "lib/Conversion/GPUCommon/GPUOpsLowering.cpp", "lib/Conversion/GPUCommon/GPUToLLVMConversion.cpp", ], hdrs = ["include/mlir/Conversion/GPUCommon/GPUCommonPass.h"], @@ -6014,6 +6016,7 @@ cc_library( ":ConvertToLLVM", ":ConvertToLLVMInterface", ":FuncToLLVM", + ":GPUCommonTransforms", ":GPUDialect", ":GPUTransforms", ":IR", -- GitLab From 9c0c98ed376f8705d0856f29a7ec659120187612 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Wed, 27 Mar 2024 05:27:44 +0000 Subject: [PATCH 032/541] [llvm-debuginfo-analyzer][DOC] Convert 'README.txt' to markdown. (#86394) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As part of the WebAssembly support work https://github.com/llvm/llvm-project/pull/85566 The README.txt is a bit odd since it only lists issues and problems without talking about what works. It’s also hard to read on the GitHub web view. - Convert to Markdown and linking to the command docs https://llvm.org/docs/CommandGuide/llvm-debuginfo-analyzer - Rename some left 'elf reader' to 'DWARF reader'. --- .../CommandGuide/llvm-debuginfo-analyzer.rst | 4 + .../LogicalView/Readers/LVCodeViewReader.h | 2 +- .../LogicalView/Readers/LVDWARFReader.h | 2 +- .../LogicalView/Readers/LVDWARFReader.cpp | 4 +- llvm/tools/llvm-debuginfo-analyzer/README.md | 170 ++++++++++++++ llvm/tools/llvm-debuginfo-analyzer/README.txt | 221 ------------------ 6 files changed, 178 insertions(+), 225 deletions(-) create mode 100644 llvm/tools/llvm-debuginfo-analyzer/README.md delete mode 100644 llvm/tools/llvm-debuginfo-analyzer/README.txt diff --git a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst index 54622cc61fdf..5b3200a4b782 100644 --- a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst +++ b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst @@ -2267,6 +2267,10 @@ EXIT STATUS :program:`llvm-debuginfo-analyzer` returns 0 if the input files were parsed and printed successfully. Otherwise, it returns 1. +LIMITATIONS AND KNOWN ISSUES +---------------------------- +See :download:`Limitations <../../tools/llvm-debuginfo-analyzer/README.md>`. + SEE ALSO -------- :manpage:`llvm-dwarfdump` diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h index 8a32210bac3c..4dd7c967ddc1 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h @@ -58,7 +58,7 @@ class LVSymbolVisitorDelegate; using LVNames = SmallVector; -// The ELF reader uses the DWARF constants to create the logical elements. +// The DWARF reader uses the DWARF constants to create the logical elements. // The DW_TAG_* and DW_AT_* are used to select the logical object and to // set specific attributes, such as name, type, etc. // As the CodeView constants are different to the DWARF constants, the diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h index 22e804a459f8..fdc97249d8e5 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h @@ -49,7 +49,7 @@ class LVDWARFReader final : public LVBinaryReader { // In DWARF v4, the files are 1-indexed. // In DWARF v5, the files are 0-indexed. - // The ELF reader expects the indexes as 1-indexed. + // The DWARF reader expects the indexes as 1-indexed. bool IncrementFileIndex = false; // Address ranges collected for current DIE. diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 91e5a037054d..6a97bed9e3a8 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -878,7 +878,7 @@ Error LVDWARFReader::createScopes() { // Additional discussions here: // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00883.html - // The ELF Reader is expecting the files are 1-indexed, so using + // The DWARF reader is expecting the files are 1-indexed, so using // the .debug_line header information decide if the indexed require // an internal adjustment. @@ -918,7 +918,7 @@ Error LVDWARFReader::createScopes() { // DWARF-5 -> Increment index. return true; }; - // The ELF reader expects the indexes as 1-indexed. + // The DWARF reader expects the indexes as 1-indexed. IncrementFileIndex = DeduceIncrementFileIndex(); DWARFDie UnitDie = CU->getUnitDIE(); diff --git a/llvm/tools/llvm-debuginfo-analyzer/README.md b/llvm/tools/llvm-debuginfo-analyzer/README.md new file mode 100644 index 000000000000..28c4be6f7322 --- /dev/null +++ b/llvm/tools/llvm-debuginfo-analyzer/README.md @@ -0,0 +1,170 @@ +# `llvm-debuginfo-analyzer` + +These are the notes collected during the development, review and test. +They describe limitations, known issues and future work. + +### Remove the use of macros in ``LVReader.h`` that describe the ``bumpallocators``. +**[D137933](https://reviews.llvm.org/D137933#inline-1389904)** + +Use a standard (or LLVM) ``map`` with ``typeinfo`` (would need a specialization +to expose equality and hasher) for the allocators and the creation +functions could be a function template. + +### Use a **lit test** instead of a **unit test** for the **logical readers**. +**[D125783](https://reviews.llvm.org/D125783#inline-1324376)** + +As the ``DebugInfoLogicalView`` library is sufficiently exposed via the +``llvm-debuginfo-analyzer`` tool, follow the LLVM general approach and +use ``lit`` tests to validate the **logical readers**. + +Convert the ``unitests``: +``` +llvm-project/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp +llvm-project/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp +``` +into ``lit`` tests: +``` +llvm-project/llvm/test/DebugInfo/LogicalView/CodeViewReader.test +llvm-project/llvm/test/DebugInfo/LogicalView/DWARFReader.test +``` + +### Eliminate calls to ``getInputFileDirectory()`` in the ``unittests``. +**[D125783](https://reviews.llvm.org/D125783#inline-1324359)** + +Rewrite the unittests ``ReaderTest`` and ``CodeViewReaderTest`` to eliminate +the call: +``` + getInputFileDirectory() +``` +as use of that call is discouraged. + +### Fix mismatch between ``%d/%x`` format strings and ``uint64_t`` type. +**[D137400](https://reviews.llvm.org/D137400) / [58758](https://github.com/llvm/llvm-project/issues/58758)** + +Incorrect printing of ``uint64_t`` on ``32-bit`` platforms. +Add the ``PRIx64`` specifier to the printing code (``format()``). + +### Remove ``LVScope::Children`` container. +**[D137933](https://reviews.llvm.org/D137933#inline-1373902)** + +Use a **chaining iterator** over the other containers rather than keep a +separate container ``Children`` that mirrors their contents. + +### Use ``TableGen`` for command line options. +**[D125777](https://reviews.llvm.org/D125777#inline-1291801)** + +The current trend is to use ``TableGen`` for command-line options in tools. +Change command line options to use ``tablegen`` as many other LLVM tools. + +### ``LVDoubleMap`` to return ``optional`` instead of ``null pointer``. +**[D125783](https://reviews.llvm.org/D125783#inline-1294164)** + +The more idiomatic LLVM way to handle this would be to have ``find`` +return ``Optional``. + +### Pass references instead of pointers (**Comparison functions**). +**[D125782](https://reviews.llvm.org/D125782#inline-1293920)** + +In the **comparison functions**, pass references instead of pointers (when +pointers cannot be null). + +### Use ``StringMap`` where possible. +**[D125783](https://reviews.llvm.org/D125783#inline-1294211)** + +LLVM has a ``StringMap`` class that is advertised as more efficient than +``std::map``. Mainly it does fewer allocations +because the key is not a ``std::string``. + +Replace the use of ``std::map`` with ``StringMap``. +One specific case is the ``LVSymbolNames`` definitions. + +### Calculate unique offset for CodeView elements. +In order to have the same logical functionality as the DWARF reader, such +as: + +* find scopes contribution to debug info +* sort by its physical location + +The logical elements must have an unique offset (similar like the DWARF +``DIE`` offset). + +### Move ``initializeFileAndStringTables`` to the CodeView Library. +There is some code in the CodeView reader that was extracted/adapted +from ``tools/llvm-readobj/COFFDumper.cpp`` that can be moved to the CodeView +library. + +We had a similar case with code shared with ``llvm-pdbutil`` that was moved +to the PDB library: **[D122226](https://reviews.llvm.org/D122226)** + +### Move ``getSymbolKindName`` and ``formatRegisterId`` to the CodeView Library. +There is some code in the CodeView reader that was extracted/adapted +from ``lib/DebugInfo/CodeView/SymbolDumper.cpp`` that can be used. + +### Use of ``std::unordered_set`` instead of ``std::set``. +**[D125784](https://reviews.llvm.org/D125784#inline-1221421)** + +Replace the ``std::set`` usage for ``DeducedScopes``, ``UnresolvedScopes`` and +``IdentifiedNamespaces`` with ``std::unordered_set`` and get the benefit +of the O(1) while inserting/searching, as the order is not important. + +### Optimize ``LVNamespaceDeduction::find`` funtion. +**[D125784](https://reviews.llvm.org/D125784#inline-1296195)** + +Optimize the ``find`` method to use the proposed code: + +``` + LVStringRefs::iterator Iter = std::find_if(Components.begin(), Components.end(), + [](StringRef Name) { + return IdentifiedNamespaces.find(Name) == IdentifiedNamespaces.end(); + }); + LVStringRefs::size_type FirstNonNamespace = std::distance(Components.begin(), Iter); +``` + +### Move all the printing support to a common module. +Factor out printing functionality from the logical elements into a +common module. + +### Refactor ``LVBinaryReader::processLines``. +**[D125783](https://reviews.llvm.org/D125783#inline-1246155) / +[D137156](https://reviews.llvm.org/D137156)** + +During the traversal of the debug information sections, we created the +logical lines representing the **disassembled instructions** from the **text +section** and the logical lines representing the **line records** from the +**debug line** section. Using the ranges associated with the logical scopes, +we will allocate those logical lines to their logical scopes. + +Consider the case when any of those lines become orphans, causing +incorrect scope parent for disassembly or line records. + +### Add support for ``-ffunction-sections``. +**[D125783](https://reviews.llvm.org/D125783#inline-1295012)** + +Only linked executables are handled. It does not support relocatable +files compiled with ``-ffunction-sections``. + +### Add support for DWARF v5 `.debug_names` section / CodeView public symbols stream. +**[D125783](https://reviews.llvm.org/D125783#inline-1294142)** + +The DWARF and CodeView readers use the public names information to create +the instructions (``LVLineAssembler``). Instead of relying on DWARF section +names (``.debug_pubnames``, ``.debug_names``) and CodeView public symbol stream +(``S_PUB32``), the readers should collect the needed information while processing +the debug information. + +If the object file supports the above section names and stream, use them +to create the public names. + +### Add support for some extra DWARF locations. +The following DWARF debug location operands are not supported: + +* `DW_OP_const_type` +* `DW_OP_entry_value` +* `DW_OP_implicit_value` + +### Add support for additional binary formats. +* Extended COFF (`XCOFF`) + +### Add support for ``JSON`` or ``YAML`` +The logical view uses its own and non-standard free form text when +displaying information on logical elements. diff --git a/llvm/tools/llvm-debuginfo-analyzer/README.txt b/llvm/tools/llvm-debuginfo-analyzer/README.txt deleted file mode 100644 index ce7569d27224..000000000000 --- a/llvm/tools/llvm-debuginfo-analyzer/README.txt +++ /dev/null @@ -1,221 +0,0 @@ -//===- llvm/tools/llvm-debuginfo-analyzer/README.txt ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains notes collected during the development, review and test. -// It describes limitations, know issues and future work. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Remove the use of macros in 'LVReader.h' that describe the bumpallocators. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D137933#inline-1389904 - -Use a standard (or LLVM) map with typeinfo (would need a specialization -to expose equality and hasher) for the allocators and the creation -functions could be a function template. - -//===----------------------------------------------------------------------===// -// Use a lit test instead of a unit test for the logical readers. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1324376 - -As the DebugInfoLogicalView library is sufficiently exposed via the -llvm-debuginfo-analyzer tool, follow the LLVM general approach and -use LIT tests to validate the logical readers. - -Convert the unitests: - llvm-project/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp - llvm-project/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp - -into LIT tests: - llvm-project/llvm/test/DebugInfo/LogicalView/CodeViewReader.test - llvm-project/llvm/test/DebugInfo/LogicalView/DWARFReader.test - -//===----------------------------------------------------------------------===// -// Eliminate calls to 'getInputFileDirectory()' in the unit tests. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1324359 - -Rewrite the unittests 'LFReaderTest' and 'CodeViewReaderTest'to eliminate -the call: - - getInputFileDirectory() - -as use of that call is discouraged. - -See: Use a lit test instead of a unit test for the logical readers. - -//===----------------------------------------------------------------------===// -// Fix mismatch between %d/%x format strings and uint64_t type. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D137400 -https://github.com/llvm/llvm-project/issues/58758 - -Incorrect printing of uint64_t on 32-bit platforms. -Add the PRIx64 specifier to the printing code (format()). - -//===----------------------------------------------------------------------===// -// Remove 'LVScope::Children' container. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D137933#inline-1373902 - -Use a chaining iterator over the other containers rather than keep a -separate container 'Children' that mirrors their contents. - -//===----------------------------------------------------------------------===// -// Use TableGen for command line options. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125777#inline-1291801 - -The current trend is to use TableGen for command-line options in tools. -Change command line options to use tablegen as many other LLVM tools. - -//===----------------------------------------------------------------------===// -// LVDoubleMap to return optional instead of null pointer. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1294164 - -The more idiomatic LLVM way to handle this would be to have 'find ' -return Optional. - -//===----------------------------------------------------------------------===// -// Pass references instead of pointers (Comparison functions). -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125782#inline-1293920 - -In the comparison functions, pass references instead of pointers (when -pointers cannot be null). - -//===----------------------------------------------------------------------===// -// Use StringMap where possible. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1294211 - -LLVM has a StringMap class that is advertised as more efficient than -std::map. Mainly it does fewer allocations -because the key is not a std::string. - -Replace the use of std::map with String Map. -One specific case is the LVSymbolNames definitions. - -//===----------------------------------------------------------------------===// -// Calculate unique offset for CodeView elements. -//===----------------------------------------------------------------------===// -In order to have the same logical functionality as the ELF Reader, such -as: - -- find scopes contribution to debug info -- sort by its physical location - -The logical elements must have an unique offset (similar like the DWARF -DIE offset). - -//===----------------------------------------------------------------------===// -// Move 'initializeFileAndStringTables' to the COFF Library. -//===----------------------------------------------------------------------===// -There is some code in the CodeView reader that was extracted/adapted -from 'tools/llvm-readobj/COFFDumper.cpp' that can be moved to the COFF -library. - -We had a similar case with code shared with llvm-pdbutil that was moved -to the PDB library: https://reviews.llvm.org/D122226 - -//===----------------------------------------------------------------------===// -// Move 'getSymbolKindName'/'formatRegisterId' to the CodeView Library. -//===----------------------------------------------------------------------===// -There is some code in the CodeView reader that was extracted/adapted -from 'lib/DebugInfo/CodeView/SymbolDumper.cpp' that can be used. - -//===----------------------------------------------------------------------===// -// Use of std::unordered_set instead of std::set. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125784#inline-1221421 - -Replace the std::set usage for DeducedScopes, UnresolvedScopes and -IdentifiedNamespaces with std::unordered_set and get the benefit -of the O(1) while inserting/searching, as the order is not important. - -//===----------------------------------------------------------------------===// -// Optimize 'LVNamespaceDeduction::find' funtion. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125784#inline-1296195 - -Optimize the 'find' method to use the proposed code: - - LVStringRefs::iterator Iter = std::find_if(Components.begin(), Components.end(), - [](StringRef Name) { - return IdentifiedNamespaces.find(Name) == IdentifiedNamespaces.end(); - }); - LVStringRefs::size_type FirstNonNamespace = std::distance(Components.begin(), Iter); - -//===----------------------------------------------------------------------===// -// Move all the printing support to a common module. -//===----------------------------------------------------------------------===// -Factor out printing functionality from the logical elements into a -common module. - -//===----------------------------------------------------------------------===// -// Refactor 'LVBinaryReader::processLines'. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1246155 -https://reviews.llvm.org/D137156 - -During the traversal of the debug information sections, we created the -logical lines representing the disassembled instructions from the text -section and the logical lines representing the line records from the -debug line section. Using the ranges associated with the logical scopes, -we will allocate those logical lines to their logical scopes. - -Consider the case when any of those lines become orphans, causing -incorrect scope parent for disassembly or line records. - -//===----------------------------------------------------------------------===// -// Add support for '-ffunction-sections'. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1295012 - -Only linked executables are handled. It does not support relocatable -files compiled with -ffunction-sections. - -//===----------------------------------------------------------------------===// -// Add support for DWARF v5 .debug_names section. -// Add support for CodeView public symbols stream. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1294142 - -The ELF and CodeView readers use the public names information to create -the instructions (LVLineAssembler). Instead of relying on DWARF section -names (.debug_pubnames, .debug_names) and CodeView public symbol stream -(S_PUB32), the readers collects the needed information while processing -the debug information. - -If the object file supports the above section names and stream, use them -to create the public names. - -//===----------------------------------------------------------------------===// -// Add support for some extra DWARF locations. -//===----------------------------------------------------------------------===// -The following DWARF debug location operands are not supported: - -- DW_OP_const_type -- DW_OP_entry_value -- DW_OP_implicit_value - -//===----------------------------------------------------------------------===// -// Add support for additional binary formats. -//===----------------------------------------------------------------------===// -- Extended COFF (XCOFF) - -//===----------------------------------------------------------------------===// -// Add support for JSON or YAML. -//===----------------------------------------------------------------------===// -The logical view uses its own and non-standard free form text when -displaying information on logical elements. - -//===----------------------------------------------------------------------===// -- GitLab From 22bfc58cd08cd58c8866ef79f3529d314dcb77e5 Mon Sep 17 00:00:00 2001 From: Yeting Kuo <46629943+yetingk@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:40:38 +0800 Subject: [PATCH 033/541] [RISCV] Teach RISCVMakeCompressible handle byte/half load/store for Zcb. (#83375) For targets with Zcb, this patch makes llvm generate more compress c.lb/lbu/lh/lhu/sb/sh instructions. --- .../Target/RISCV/RISCVMakeCompressible.cpp | 50 +- .../CodeGen/RISCV/make-compressible-zbc.mir | 585 ++++++++++++++++++ 2 files changed, 632 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/make-compressible-zbc.mir diff --git a/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp b/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp index af864ba0fbc4..3f423450618d 100644 --- a/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp +++ b/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp @@ -99,6 +99,13 @@ static unsigned log2LdstWidth(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unexpected opcode"); + case RISCV::LBU: + case RISCV::SB: + return 0; + case RISCV::LH: + case RISCV::LHU: + case RISCV::SH: + return 1; case RISCV::LW: case RISCV::SW: case RISCV::FLW: @@ -112,17 +119,47 @@ static unsigned log2LdstWidth(unsigned Opcode) { } } +// Return bit field size of immediate operand of Opcode. +static unsigned offsetMask(unsigned Opcode) { + switch (Opcode) { + default: + llvm_unreachable("Unexpected opcode"); + case RISCV::LBU: + case RISCV::SB: + return maskTrailingOnes(2U); + case RISCV::LH: + case RISCV::LHU: + case RISCV::SH: + return maskTrailingOnes(1U); + case RISCV::LW: + case RISCV::SW: + case RISCV::FLW: + case RISCV::FSW: + case RISCV::LD: + case RISCV::SD: + case RISCV::FLD: + case RISCV::FSD: + return maskTrailingOnes(5U); + } +} + // Return a mask for the offset bits of a non-stack-pointer based compressed // load/store. static uint8_t compressedLDSTOffsetMask(unsigned Opcode) { - return 0x1f << log2LdstWidth(Opcode); + return offsetMask(Opcode) << log2LdstWidth(Opcode); } // Return true if Offset fits within a compressed stack-pointer based // load/store. static bool compressibleSPOffset(int64_t Offset, unsigned Opcode) { - return log2LdstWidth(Opcode) == 2 ? isShiftedUInt<6, 2>(Offset) - : isShiftedUInt<6, 3>(Offset); + // Compressed sp-based loads and stores only work for 32/64 bits. + switch (log2LdstWidth(Opcode)) { + case 2: + return isShiftedUInt<6, 2>(Offset); + case 3: + return isShiftedUInt<6, 3>(Offset); + } + return false; } // Given an offset for a load/store, return the adjustment required to the base @@ -147,6 +184,10 @@ static bool isCompressibleLoad(const MachineInstr &MI) { switch (MI.getOpcode()) { default: return false; + case RISCV::LBU: + case RISCV::LH: + case RISCV::LHU: + return STI.hasStdExtZcb(); case RISCV::LW: case RISCV::LD: return STI.hasStdExtCOrZca(); @@ -164,6 +205,9 @@ static bool isCompressibleStore(const MachineInstr &MI) { switch (MI.getOpcode()) { default: return false; + case RISCV::SB: + case RISCV::SH: + return STI.hasStdExtZcb(); case RISCV::SW: case RISCV::SD: return STI.hasStdExtCOrZca(); diff --git a/llvm/test/CodeGen/RISCV/make-compressible-zbc.mir b/llvm/test/CodeGen/RISCV/make-compressible-zbc.mir new file mode 100644 index 000000000000..89a6ca7af9be --- /dev/null +++ b/llvm/test/CodeGen/RISCV/make-compressible-zbc.mir @@ -0,0 +1,585 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -o - %s -mtriple=riscv32 -mattr=+zcb -simplify-mir \ +# RUN: -run-pass=riscv-make-compressible | FileCheck --check-prefixes=CHECK %s +# RUN: llc -o - %s -mtriple=riscv64 -mattr=+zcb -simplify-mir \ +# RUN: -run-pass=riscv-make-compressible | FileCheck --check-prefixes=CHECK %s + +--- | + define void @store_common_value_i8(ptr %a, ptr %b, ptr %c) #0 { + entry: + store i8 0, ptr %a, align 1 + store i8 0, ptr %b, align 1 + store i8 0, ptr %c, align 1 + ret void + } + + define void @store_common_value_i16(ptr %a, ptr %b, ptr %c) #0 { + entry: + store i16 0, ptr %a, align 2 + store i16 0, ptr %b, align 2 + store i16 0, ptr %c, align 2 + ret void + } + + define void @store_common_ptr_i8(ptr %p) #0 { + entry: + store volatile i8 1, ptr %p, align 1 + store volatile i8 3, ptr %p, align 1 + store volatile i8 5, ptr %p, align 1 + ret void + } + + define void @store_common_ptr_i16(ptr %p) #0 { + entry: + store volatile i16 1, ptr %p, align 2 + store volatile i16 3, ptr %p, align 2 + store volatile i16 5, ptr %p, align 2 + ret void + } + + define void @load_common_ptr_i8(ptr %p) #0 { + entry: + %0 = load volatile i8, ptr %p, align 1 + %a = sext i8 %0 to i32 + %1 = load volatile i8, ptr %p, align 1 + %2 = load volatile i8, ptr %p, align 1 + ret void + } + + define void @load_common_ptr_s16(ptr %p) #0 { + entry: + %0 = load volatile i16, ptr %p, align 2 + %1 = load volatile i16, ptr %p, align 2 + %2 = load volatile i16, ptr %p, align 2 + ret void + } + + define void @load_common_ptr_u16(ptr %p) #0 { + entry: + %0 = load volatile i16, ptr %p, align 2 + %1 = load volatile i16, ptr %p, align 2 + %2 = load volatile i16, ptr %p, align 2 + ret void + } + + define void @store_large_offset_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + store volatile i8 1, ptr %0, align 1 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + store volatile i8 3, ptr %1, align 1 + %2 = getelementptr inbounds i8, ptr %p, i8 102 + store volatile i8 5, ptr %2, align 1 + %3 = getelementptr inbounds i8, ptr %p, i8 103 + store volatile i8 7, ptr %3, align 1 + ret void + } + + define void @store_large_offset_i16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + store volatile i16 1, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + store volatile i16 3, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + store volatile i16 3, ptr %1, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 101 + store volatile i16 7, ptr %3, align 2 + ret void + } + + define void @load_large_offset_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + %a = load volatile i8, ptr %0 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + %b = load volatile i8, ptr %1 + %2 = getelementptr inbounds i8, ptr %p, i8 102 + %c = load volatile i8, ptr %2 + %3 = getelementptr inbounds i8, ptr %p, i8 103 + %d = load volatile i8, ptr %3 + ret void + } + + define void @load_large_offset_s16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + %b = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %2, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 101 + %d = load volatile i16, ptr %3, align 2 + ret void + } + + define void @load_large_offset_u16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + %b = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %2, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 101 + %d = load volatile i16, ptr %3, align 2 + ret void + } + define void @store_large_offset_no_opt_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + store volatile i8 1, ptr %0, align 1 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + store volatile i8 3, ptr %1, align 1 + %2 = getelementptr inbounds i8, ptr %p, i8 104 + store volatile i8 5, ptr %2, align 1 + ret void + } + + define void @store_large_offset_no_opt_i16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + %b = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %2, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 102 + %d = load volatile i16, ptr %3, align 2 + ret void + } + + define void @load_large_offset_no_opt_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + %a = load volatile i8, ptr %0 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + %b = load volatile i8, ptr %1 + %2 = getelementptr inbounds i8, ptr %p, i8 103 + %c = load volatile i8, ptr %2 + ret void + } + + define void @load_large_offset_no_opt_s16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 102 + %d = load volatile i16, ptr %2, align 2 + ret void + } + + define void @load_large_offset_no_opt_u16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 102 + %d = load volatile i16, ptr %2, align 2 + ret void + } + attributes #0 = { minsize } + +... +--- +name: store_common_value_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10, $x11, $x12 + + ; CHECK-LABEL: name: store_common_value_i8 + ; CHECK: liveins: $x10, $x11, $x12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x13 = ADDI $x0, 0 + ; CHECK-NEXT: SB $x13, killed renamable $x10, 0 :: (store (s8) into %ir.a) + ; CHECK-NEXT: SB $x13, killed renamable $x11, 0 :: (store (s8) into %ir.b) + ; CHECK-NEXT: SB $x13, killed renamable $x12, 0 :: (store (s8) into %ir.c) + ; CHECK-NEXT: PseudoRET + SB $x0, killed renamable $x10, 0 :: (store (s8) into %ir.a) + SB $x0, killed renamable $x11, 0 :: (store (s8) into %ir.b) + SB $x0, killed renamable $x12, 0 :: (store (s8) into %ir.c) + PseudoRET + +... +--- +name: store_common_value_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10, $x11, $x12 + + ; CHECK-LABEL: name: store_common_value_i16 + ; CHECK: liveins: $x10, $x11, $x12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x13 = ADDI $x0, 0 + ; CHECK-NEXT: SH $x13, killed renamable $x10, 0 :: (store (s16) into %ir.a) + ; CHECK-NEXT: SH $x13, killed renamable $x11, 0 :: (store (s16) into %ir.b) + ; CHECK-NEXT: SH $x13, killed renamable $x12, 0 :: (store (s16) into %ir.c) + ; CHECK-NEXT: PseudoRET + SH $x0, killed renamable $x10, 0 :: (store (s16) into %ir.a) + SH $x0, killed renamable $x11, 0 :: (store (s16) into %ir.b) + SH $x0, killed renamable $x12, 0 :: (store (s16) into %ir.c) + PseudoRET + +... +--- +name: store_common_ptr_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_common_ptr_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 1 + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: SB killed renamable $x10, $x11, 0 :: (volatile store (s8) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 3 + ; CHECK-NEXT: SB killed renamable $x10, $x11, 0 :: (volatile store (s8) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 5 + ; CHECK-NEXT: SB killed renamable $x10, killed $x11, 0 :: (volatile store (s8) into %ir.p) + ; CHECK-NEXT: PseudoRET + renamable $x10 = ADDI $x0, 1 + SB killed renamable $x10, renamable $x16, 0 :: (volatile store (s8) into %ir.p) + renamable $x10 = ADDI $x0, 3 + SB killed renamable $x10, renamable $x16, 0 :: (volatile store (s8) into %ir.p) + renamable $x10 = ADDI $x0, 5 + SB killed renamable $x10, killed renamable $x16, 0 :: (volatile store (s8) into %ir.p) + PseudoRET + +... +--- +name: store_common_ptr_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_common_ptr_i16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 1 + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: SH killed renamable $x10, $x11, 0 :: (volatile store (s16) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 3 + ; CHECK-NEXT: SH killed renamable $x10, $x11, 0 :: (volatile store (s16) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 5 + ; CHECK-NEXT: SH killed renamable $x10, killed $x11, 0 :: (volatile store (s16) into %ir.p) + ; CHECK-NEXT: PseudoRET + renamable $x10 = ADDI $x0, 1 + SH killed renamable $x10, renamable $x16, 0 :: (volatile store (s16) into %ir.p) + renamable $x10 = ADDI $x0, 3 + SH killed renamable $x10, renamable $x16, 0 :: (volatile store (s16) into %ir.p) + renamable $x10 = ADDI $x0, 5 + SH killed renamable $x10, killed renamable $x16, 0 :: (volatile store (s16) into %ir.p) + PseudoRET + +... +--- +name: load_common_ptr_i8 +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_common_ptr_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: dead $x10 = LBU $x11, 0 :: (volatile load (s8) from %ir.p) + ; CHECK-NEXT: dead $x10 = LBU $x11, 0 :: (volatile load (s8) from %ir.p) + ; CHECK-NEXT: dead $x10 = LBU killed $x11, 0 :: (volatile load (s8) from %ir.p) + ; CHECK-NEXT: PseudoRET + dead $x10 = LBU renamable $x16, 0 :: (volatile load (s8) from %ir.p) + dead $x10 = LBU renamable $x16, 0 :: (volatile load (s8) from %ir.p) + dead $x10 = LBU killed renamable $x16, 0 :: (volatile load (s8) from %ir.p) + PseudoRET + +... +--- +name: load_common_ptr_s16 +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_common_ptr_s16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LH killed $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: PseudoRET + dead $x10 = LH renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LH renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LH killed renamable $x16, 0 :: (volatile load (s16) from %ir.p) + PseudoRET + +... +--- +name: load_common_ptr_u16 +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_common_ptr_u16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LHU killed $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: PseudoRET + dead $x10 = LHU renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LHU renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LHU killed renamable $x16, 0 :: (volatile load (s16) from %ir.p) + PseudoRET + +... +--- +name: store_large_offset_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10 + + ; CHECK-LABEL: name: store_large_offset_i8 + ; CHECK: liveins: $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: $x12 = ADDI $x10, 100 + ; CHECK-NEXT: SB killed renamable $x11, $x12, 0 :: (volatile store (s8) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SB killed renamable $x11, $x12, 1 :: (volatile store (s8) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SB killed renamable $x11, $x12, 2 :: (volatile store (s8) into %ir.2) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 7 + ; CHECK-NEXT: SB killed renamable $x11, killed $x12, 3 :: (volatile store (s8) into %ir.3) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SB killed renamable $x11, renamable $x10, 100 :: (volatile store (s8) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SB killed renamable $x11, renamable $x10, 101 :: (volatile store (s8) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SB killed renamable $x11, renamable $x10, 102 :: (volatile store (s8) into %ir.2) + renamable $x11 = ADDI $x0, 7 + SB killed renamable $x11, killed renamable $x10, 103 :: (volatile store (s8) into %ir.3) + PseudoRET + +... +--- +name: store_large_offset_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10 + ; CHECK-LABEL: name: store_large_offset_i16 + ; CHECK: liveins: $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: $x12 = ADDI $x10, 200 + ; CHECK-NEXT: SH killed renamable $x11, $x12, 0 :: (volatile store (s16) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SH killed renamable $x11, $x12, 0 :: (volatile store (s16) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SH killed renamable $x11, $x12, 2 :: (volatile store (s16) into %ir.2) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 7 + ; CHECK-NEXT: SH killed renamable $x11, killed $x12, 2 :: (volatile store (s16) into %ir.3) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SH killed renamable $x11, renamable $x10, 200 :: (volatile store (s16) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SH killed renamable $x11, renamable $x10, 200 :: (volatile store (s16) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SH killed renamable $x11, renamable $x10, 202 :: (volatile store (s16) into %ir.2) + renamable $x11 = ADDI $x0, 7 + SH killed renamable $x11, killed renamable $x10, 202 :: (volatile store (s16) into %ir.3) + PseudoRET + +... +--- +name: load_large_offset_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 100 + ; CHECK-NEXT: dead $x10 = LBU $x11, 0 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LBU $x11, 1 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LBU $x11, 2 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: dead $x10 = LBU killed $x11, 3 :: (volatile load (s8) from %ir.3) + ; CHECK-NEXT: PseudoRET + dead $x10 = LBU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LBU renamable $x16, 101 :: (volatile load (s8) from %ir.1) + dead $x10 = LBU renamable $x16, 102 :: (volatile load (s8) from %ir.2) + dead $x10 = LBU killed renamable $x16, 103 :: (volatile load (s8) from %ir.3) + PseudoRET + +... +--- +name: load_large_offset_s16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_s16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 100 + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.0) + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.1) + ; CHECK-NEXT: dead $x10 = LH $x11, 2 :: (volatile load (s16) from %ir.2) + ; CHECK-NEXT: dead $x10 = LH killed $x11, 2 :: (volatile load (s16) from %ir.3) + ; CHECK-NEXT: PseudoRET + dead $x10 = LH renamable $x16, 100 :: (volatile load (s16) from %ir.0) + dead $x10 = LH renamable $x16, 100 :: (volatile load (s16) from %ir.1) + dead $x10 = LH renamable $x16, 102 :: (volatile load (s16) from %ir.2) + dead $x10 = LH killed renamable $x16, 102 :: (volatile load (s16) from %ir.3) + PseudoRET + +... +--- +name: load_large_offset_u16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_u16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 100 + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.0) + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.1) + ; CHECK-NEXT: dead $x10 = LHU $x11, 2 :: (volatile load (s16) from %ir.2) + ; CHECK-NEXT: dead $x10 = LHU killed $x11, 2 :: (volatile load (s16) from %ir.3) + ; CHECK-NEXT: PseudoRET + dead $x10 = LHU renamable $x16, 100 :: (volatile load (s16) from %ir.0) + dead $x10 = LHU renamable $x16, 100 :: (volatile load (s16) from %ir.1) + dead $x10 = LHU renamable $x16, 102 :: (volatile load (s16) from %ir.2) + dead $x10 = LHU killed renamable $x16, 102 :: (volatile load (s16) from %ir.3) + PseudoRET + +... +--- +name: store_large_offset_no_opt_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_large_offset_no_opt_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: SB killed renamable $x11, renamable $x16, 100 :: (volatile store (s8) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SB killed renamable $x11, renamable $x16, 101 :: (volatile store (s8) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SB killed renamable $x11, renamable $x16, 104 :: (volatile store (s8) into %ir.2) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SB killed renamable $x11, renamable $x16, 100 :: (volatile store (s8) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SB killed renamable $x11, renamable $x16, 101 :: (volatile store (s8) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SB killed renamable $x11, renamable $x16, 104 :: (volatile store (s8) into %ir.2) + PseudoRET + +... +--- +name: store_large_offset_no_opt_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_large_offset_no_opt_i16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: SH killed renamable $x11, renamable $x16, 200 :: (volatile store (s16) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SH killed renamable $x11, renamable $x16, 202 :: (volatile store (s16) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SH killed renamable $x11, renamable $x16, 204 :: (volatile store (s16) into %ir.2) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SH killed renamable $x11, renamable $x16, 200 :: (volatile store (s16) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SH killed renamable $x11, renamable $x16, 202 :: (volatile store (s16) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SH killed renamable $x11, renamable $x16, 204 :: (volatile store (s16) into %ir.2) + PseudoRET + +... +--- +name: load_large_offset_no_opt_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_no_opt_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $x10 = LBU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LBU renamable $x16, 101 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LBU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: PseudoRET + dead $x10 = LBU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LBU renamable $x16, 101 :: (volatile load (s8) from %ir.1) + dead $x10 = LBU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + PseudoRET + +... +--- +name: load_large_offset_no_opt_s16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_no_opt_s16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $x10 = LH renamable $x16, 100 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LH renamable $x16, 102 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LH killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: PseudoRET + dead $x10 = LH renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LH renamable $x16, 102 :: (volatile load (s8) from %ir.1) + dead $x10 = LH killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + PseudoRET + +... +--- +name: load_large_offset_no_opt_u16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_no_opt_u16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $x10 = LHU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LHU renamable $x16, 102 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LHU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: PseudoRET + dead $x10 = LHU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LHU renamable $x16, 102 :: (volatile load (s8) from %ir.1) + dead $x10 = LHU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + PseudoRET + +... -- GitLab From 16993c793a7d81771ea17a2991f76e87b4b0a6c0 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Tue, 26 Mar 2024 22:39:00 -0700 Subject: [PATCH 034/541] [NFC][HWASAN] Regenerate test --- .../HWAddressSanitizer/use-after-scope-setjmp.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll index 4bb846bff274..079d72241283 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll @@ -48,8 +48,8 @@ define dso_local noundef i1 @_Z6targetv() sanitize_hwaddress { ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP26]], i8 [[TMP22]], i64 256, i1 false) ; CHECK-NEXT: [[CALL:%.*]] = call i32 @setjmp(ptr noundef @jbuf) ; CHECK-NEXT: switch i32 [[CALL]], label [[WHILE_BODY:%.*]] [ -; CHECK-NEXT: i32 1, label [[RETURN:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB1:%.*]] +; CHECK-NEXT: i32 1, label [[RETURN:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB1:%.*]] ; CHECK-NEXT: ] ; CHECK: sw.bb1: ; CHECK-NEXT: br label [[RETURN]] -- GitLab From 05a7b22a0132bebe99aabee591d3acc99d793ae1 Mon Sep 17 00:00:00 2001 From: Jianjian Guan Date: Wed, 27 Mar 2024 14:16:03 +0800 Subject: [PATCH 035/541] [RISCV] Add areInlineCompatible for riscv target (#86639) Inline a callee if its target-features are a subset of the callers target-features. --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 14 ++++++++ .../Target/RISCV/RISCVTargetTransformInfo.h | 3 ++ .../Inline/RISCV/inline-target-features.ll | 34 +++++++++++++++++++ .../Transforms/Inline/RISCV/lit.local.cfg | 2 ++ 4 files changed, 53 insertions(+) create mode 100644 llvm/test/Transforms/Inline/RISCV/inline-target-features.ll create mode 100644 llvm/test/Transforms/Inline/RISCV/lit.local.cfg diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index df289be18932..000d01b8366c 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1676,3 +1676,17 @@ bool RISCVTTIImpl::isLegalMaskedCompressStore(Type *DataTy, Align Alignment) { return false; return true; } + +bool RISCVTTIImpl::areInlineCompatible(const Function *Caller, + const Function *Callee) const { + const TargetMachine &TM = getTLI()->getTargetMachine(); + + const FeatureBitset &CallerBits = + TM.getSubtargetImpl(*Caller)->getFeatureBits(); + const FeatureBitset &CalleeBits = + TM.getSubtargetImpl(*Callee)->getFeatureBits(); + + // Inline a callee if its target-features are a subset of the callers + // target-features. + return (CallerBits & CalleeBits) == CalleeBits; +} diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h index 8daf6845dc8b..ac32aea4ce2b 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h @@ -60,6 +60,9 @@ public: : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), TLI(ST->getTargetLowering()) {} + bool areInlineCompatible(const Function *Caller, + const Function *Callee) const; + /// Return the cost of materializing an immediate for a value operand of /// a store instruction. InstructionCost getStoreImmCost(Type *VecTy, TTI::OperandValueInfo OpInfo, diff --git a/llvm/test/Transforms/Inline/RISCV/inline-target-features.ll b/llvm/test/Transforms/Inline/RISCV/inline-target-features.ll new file mode 100644 index 000000000000..b626a229a737 --- /dev/null +++ b/llvm/test/Transforms/Inline/RISCV/inline-target-features.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -mtriple=riscv64-unknown-linux-gnu -S -passes=inline | FileCheck %s +; RUN: opt < %s -mtriple=riscv64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s +; Check that we only inline when we have compatible target attributes. + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" +target triple = "riscv64-unknown-linux-gnu" + +define i32 @foo() #0 { +entry: + %call = call i32 (...) @baz() + ret i32 %call +; CHECK-LABEL: foo +; CHECK: call i32 (...) @baz() +} +declare i32 @baz(...) #0 + +define i32 @bar() #1 { +entry: + %call = call i32 @foo() + ret i32 %call +; CHECK-LABEL: bar +; CHECK: call i32 (...) @baz() +} + +define i32 @qux() #0 { +entry: + %call = call i32 @bar() + ret i32 %call +; CHECK-LABEL: qux +; CHECK: call i32 @bar() +} + +attributes #0 = { "target-cpu"="generic-rv64" "target-features"="+f,+d" } +attributes #1 = { "target-cpu"="generic-rv64" "target-features"="+f,+d,+m,+v" } diff --git a/llvm/test/Transforms/Inline/RISCV/lit.local.cfg b/llvm/test/Transforms/Inline/RISCV/lit.local.cfg new file mode 100644 index 000000000000..17351748513d --- /dev/null +++ b/llvm/test/Transforms/Inline/RISCV/lit.local.cfg @@ -0,0 +1,2 @@ +if not "RISCV" in config.root.targets: + config.unsupported = True -- GitLab From 577e0ef94fb0b4ba9f97a6f58a1961f7ba247d21 Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Tue, 26 Mar 2024 23:24:02 -0700 Subject: [PATCH 036/541] [clang][AST] Silence unused-value warnings in unittest DeclPrinterTest --- clang/unittests/AST/DeclPrinterTest.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp index 07fa02bd96e2..8a29d0544a04 100644 --- a/clang/unittests/AST/DeclPrinterTest.cpp +++ b/clang/unittests/AST/DeclPrinterTest.cpp @@ -1391,7 +1391,7 @@ TEST(DeclPrinter, TestCXXRecordDecl17) { "struct X {};" "Z A;", "A", "Z A")); - [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; } TEST(DeclPrinter, TestCXXRecordDecl18) { @@ -1402,7 +1402,7 @@ TEST(DeclPrinter, TestCXXRecordDecl18) { "struct Y{};" "Y, 2> B;", "B", "Y, 2> B")); - [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; } TEST(DeclPrinter, TestCXXRecordDecl19) { @@ -1413,7 +1413,7 @@ TEST(DeclPrinter, TestCXXRecordDecl19) { "struct Y{};" "Y, 2> B;", "B", "Y, 2> B")); - [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }; + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }; } TEST(DeclPrinter, TestCXXRecordDecl20) { ASSERT_TRUE(PrintedDeclCXX98Matches( @@ -1432,7 +1432,7 @@ TEST(DeclPrinter, TestCXXRecordDecl20) { "Outer, 5>::NestedStruct nestedInstance(100);", "nestedInstance", "Outer, 5>::NestedStruct nestedInstance(100)")); - [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }; } TEST(DeclPrinter, TestCXXRecordDecl21) { @@ -1452,7 +1452,7 @@ TEST(DeclPrinter, TestCXXRecordDecl21) { "Outer, 5>::NestedStruct nestedInstance(100);", "nestedInstance", "Outer, 5>::NestedStruct nestedInstance(100)")); - [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }; + (void)[](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }; } TEST(DeclPrinter, TestFunctionParamUglified) { -- GitLab From aa2d5d54130bd9c5e9efb9ae3eaec631f227f13b Mon Sep 17 00:00:00 2001 From: ShihPo Hung Date: Tue, 26 Mar 2024 23:09:09 -0700 Subject: [PATCH 037/541] Recommit "[RISCV][TTI] Scale the cost of the sext/zext with LMUL (#86617)" Changes in Recommit: Add an additional check on sign/zero extend to the same type. Original message: Use the destination data type to measure the LMUL size for latency/throughput cost --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 20 +- llvm/test/Analysis/CostModel/RISCV/cast.ll | 920 +++++++++--------- .../CostModel/RISCV/reduce-scalable-int.ll | 12 +- .../CostModel/RISCV/rvv-extractelement.ll | 84 +- .../CostModel/RISCV/rvv-insertelement.ll | 84 +- .../CostModel/RISCV/shuffle-broadcast.ll | 2 +- 6 files changed, 566 insertions(+), 556 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 000d01b8366c..38cdf3c47c64 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -909,23 +909,33 @@ InstructionCost RISCVTTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, if (!IsTypeLegal) return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + std::pair DstLT = getTypeLegalizationCost(Dst); + int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); - // FIXME: Need to consider vsetvli and lmul. int PowDiff = (int)Log2_32(Dst->getScalarSizeInBits()) - (int)Log2_32(Src->getScalarSizeInBits()); switch (ISD) { case ISD::SIGN_EXTEND: - case ISD::ZERO_EXTEND: - if (Src->getScalarSizeInBits() == 1) { + case ISD::ZERO_EXTEND: { + const unsigned SrcEltSize = Src->getScalarSizeInBits(); + if (SrcEltSize == 1) { // We do not use vsext/vzext to extend from mask vector. // Instead we use the following instructions to extend from mask vector: // vmv.v.i v8, 0 // vmerge.vim v8, v8, -1, v0 - return 2; + return getRISCVInstructionCost({RISCV::VMV_V_I, RISCV::VMERGE_VIM}, + DstLT.second, CostKind); } - return 1; + if ((PowDiff < 1) || (PowDiff > 3)) + return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + unsigned SExtOp[] = {RISCV::VSEXT_VF2, RISCV::VSEXT_VF4, RISCV::VSEXT_VF8}; + unsigned ZExtOp[] = {RISCV::VZEXT_VF2, RISCV::VZEXT_VF4, RISCV::VZEXT_VF8}; + unsigned Op = + (ISD == ISD::SIGN_EXTEND) ? SExtOp[PowDiff - 1] : ZExtOp[PowDiff - 1]; + return getRISCVInstructionCost(Op, DstLT.second, CostKind); + } case ISD::TRUNCATE: if (Dst->getScalarSizeInBits() == 1) { // We do not use several vncvt to truncate to mask vector. So we could diff --git a/llvm/test/Analysis/CostModel/RISCV/cast.ll b/llvm/test/Analysis/CostModel/RISCV/cast.ll index bd26c19c2f2c..14da9a3f79d7 100644 --- a/llvm/test/Analysis/CostModel/RISCV/cast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/cast.ll @@ -16,74 +16,74 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext undef to @@ -96,73 +96,73 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -179,74 +179,74 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext undef to @@ -259,73 +259,73 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -522,74 +522,74 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext undef to @@ -602,73 +602,73 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext undef to -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext undef to +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext undef to ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext undef to ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -685,74 +685,74 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext undef to @@ -765,73 +765,73 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext undef to -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext undef to +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext undef to ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext undef to ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll index 80efe912c869..30cb32ce4eaf 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll @@ -1141,7 +1141,7 @@ define signext i32 @vreduce_add_nxv4i32( %v) { define signext i32 @vwreduce_add_nxv4i16( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1157,7 +1157,7 @@ define signext i32 @vwreduce_add_nxv4i16( %v) { define signext i32 @vwreduce_uadd_nxv4i16( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1445,7 +1445,7 @@ define i64 @vreduce_add_nxv2i64( %v) { define i64 @vwreduce_add_nxv2i32( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1461,7 +1461,7 @@ define i64 @vwreduce_add_nxv2i32( %v) { define i64 @vwreduce_uadd_nxv2i32( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1597,7 +1597,7 @@ define i64 @vreduce_add_nxv4i64( %v) { define i64 @vwreduce_add_nxv4i32( %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = sext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1613,7 +1613,7 @@ define i64 @vwreduce_add_nxv4i32( %v) { define i64 @vwreduce_uadd_nxv4i32( %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext %v to +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = zext %v to ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64( %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll index 225bad6da591..aa7a90bece33 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll @@ -12,12 +12,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -66,12 +66,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -120,12 +120,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -177,12 +177,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -231,12 +231,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -285,12 +285,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -341,13 +341,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -395,13 +395,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -449,13 +449,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -506,13 +506,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -560,13 +560,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -614,13 +614,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll index 5387c8dc3594..6e1ae0216f76 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll @@ -12,12 +12,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -66,12 +66,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -120,12 +120,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -177,12 +177,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -231,12 +231,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -285,12 +285,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -341,13 +341,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -395,13 +395,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -449,13 +449,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -506,13 +506,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_0 = insertelement undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_0 = insertelement undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -560,13 +560,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_1 = insertelement undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv32i1_1 = insertelement undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -614,13 +614,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_x = insertelement undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i1_x = insertelement undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll index 46bf3152ac5b..b763198e98ba 100644 --- a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll @@ -197,7 +197,7 @@ define void @broadcast_fixed() #0{ ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %41 = shufflevector <32 x i1> undef, <32 x i1> undef, <32 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %42 = shufflevector <64 x i1> undef, <64 x i1> undef, <64 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %43 = shufflevector <128 x i1> undef, <128 x i1> undef, <128 x i32> zeroinitializer -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %44 = shufflevector <128 x i1> %ins1, <128 x i1> poison, <128 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ins2 = insertelement <2 x i8> poison, i8 3, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %45 = shufflevector <2 x i8> %ins2, <2 x i8> undef, <2 x i32> zeroinitializer -- GitLab From 6d13263d4a723689d025423562269ea6ccb6bfc2 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 27 Mar 2024 15:23:34 +0800 Subject: [PATCH 038/541] [RISCV] Add tests for combineBinOpOfZExts. NFC (#86689) Unlike add, sub and mul, we don't have widening instructions for div, rem and logical ops, so we don't have any test coverage if we were to extend combineBinOpOfZExts to handle them. Adding tests coincidentally revealed that logical ops are already narrowed as a generic DAG combine via DAGCombiner::hoistLogicOpWithSameOpcodeHands. So we don't actually need to run combineBinOpOfZExts on them. --- llvm/test/CodeGen/RISCV/rvv/binop-zext.ll | 146 ++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 llvm/test/CodeGen/RISCV/rvv/binop-zext.ll diff --git a/llvm/test/CodeGen/RISCV/rvv/binop-zext.ll b/llvm/test/CodeGen/RISCV/rvv/binop-zext.ll new file mode 100644 index 000000000000..e050240f0de1 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/binop-zext.ll @@ -0,0 +1,146 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck %s + +; Check that we perform binary arithmetic in a narrower type where possible, via +; combineBinOpOfZExt or otherwise. + +define @add( %a, %b) { +; CHECK-LABEL: add: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwaddu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %add = add %a.zext, %b.zext + ret %add +} + +define @sub( %a, %b) { +; CHECK-LABEL: sub: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwsubu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %sub = sub %a.zext, %b.zext + ret %sub +} + +define @mul( %a, %b) { +; CHECK-LABEL: mul: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwmulu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %mul = mul %a.zext, %b.zext + ret %mul +} + +define @sdiv( %a, %b) { +; CHECK-LABEL: sdiv: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v16, v9 +; CHECK-NEXT: vdivu.vv v8, v12, v16 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %sdiv = sdiv %a.zext, %b.zext + ret %sdiv +} + +define @udiv( %a, %b) { +; CHECK-LABEL: udiv: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v16, v9 +; CHECK-NEXT: vdivu.vv v8, v12, v16 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %udiv = udiv %a.zext, %b.zext + ret %udiv +} + +define @srem( %a, %b) { +; CHECK-LABEL: srem: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v16, v9 +; CHECK-NEXT: vremu.vv v8, v12, v16 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %srem = srem %a.zext, %b.zext + ret %srem +} + +define @urem( %a, %b) { +; CHECK-LABEL: urem: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v16, v9 +; CHECK-NEXT: vremu.vv v8, v12, v16 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %urem = urem %a.zext, %b.zext + ret %urem +} + +define @and( %a, %b) { +; CHECK-LABEL: and: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vand.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %shl = and %a.zext, %b.zext + ret %shl +} + +define @or( %a, %b) { +; CHECK-LABEL: or: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vor.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %or = or %a.zext, %b.zext + ret %or +} + +define @xor( %a, %b) { +; CHECK-LABEL: xor: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vxor.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext %a to + %b.zext = zext %b to + %xor = xor %a.zext, %b.zext + ret %xor +} -- GitLab From defc4859b032ccaec69f24b6cfd9882fece5f093 Mon Sep 17 00:00:00 2001 From: Jack Styles <99514724+Stylie777@users.noreply.github.com> Date: Wed, 27 Mar 2024 07:49:38 +0000 Subject: [PATCH 039/541] [AArch64] Remove Automatic Enablement of FEAT_F32MM (#85203) When `+sve` is passed in the command line, if the Architecture being targeted is V8.6A/V9.1A or later, `+f32mm` is also added. This enables FEAT_32MM, however at the time of writing no CPU's support this. This leads to the FEAT_32MM instructions being compiled for CPU's that do not support them. This commit removes the automatic enablement, however the option is still able to be used by passing `+f32mm`. --- clang/test/Driver/aarch64-sve.c | 9 ++++----- clang/test/Preprocessor/aarch64-target-features.c | 2 +- llvm/docs/ReleaseNotes.rst | 1 + llvm/lib/TargetParser/AArch64TargetParser.cpp | 5 ----- llvm/unittests/TargetParser/TargetParserTest.cpp | 15 ++++----------- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/clang/test/Driver/aarch64-sve.c b/clang/test/Driver/aarch64-sve.c index f34b2700deb9..4a33c2e3c8d3 100644 --- a/clang/test/Driver/aarch64-sve.c +++ b/clang/test/Driver/aarch64-sve.c @@ -6,12 +6,11 @@ // RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-NOSVE %s // GENERICV8A-NOSVE-NOT: "-target-feature" "+sve" -// The 32-bit floating point matrix multiply extension is enabled by default -// for armv8.6-a targets (or later) with SVE, and can optionally be enabled for -// any target from armv8.2a onwards (we don't enforce not using it with earlier -// targets). +// The 32-bit floating point matrix multiply extension is an optional feature +// that can be used for any target from armv8.2a and onwards. This can be +// enabled using the `+f32mm` option.`. // RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=NO-F32MM %s -// RUN: %clang --target=aarch64 -march=armv8.6a+sve -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s +// RUN: %clang --target=aarch64 -march=armv8.6a+sve+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s // RUN: %clang --target=aarch64 -march=armv8.5a+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s // NO-F32MM-NOT: "-target-feature" "+f32mm" // F32MM: "-target-feature" "+f32mm" diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 9f8a8bdeeb9c..85762b7fed4d 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -196,7 +196,7 @@ // CHECK-8_6-NOT: __ARM_FEATURE_SHA3 1 // CHECK-8_6-NOT: __ARM_FEATURE_SM4 1 -// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve+f32mm -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s // CHECK-SVE-8_6: __ARM_FEATURE_SVE 1 // CHECK-SVE-8_6: __ARM_FEATURE_SVE_BF16 1 // CHECK-SVE-8_6: __ARM_FEATURE_SVE_MATMUL_FP32 1 diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index c2b1a9d3d738..7588048334d7 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -76,6 +76,7 @@ Changes to the AMDGPU Backend Changes to the ARM Backend -------------------------- +* FEAT_F32MM is no longer activated by default when using `+sve` on v8.6-A or greater. The feature is still available and can be used by adding `+f32mm` to the command line options. Changes to the AVR Backend -------------------------- diff --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp index e36832f563ee..71099462d5ec 100644 --- a/llvm/lib/TargetParser/AArch64TargetParser.cpp +++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp @@ -186,11 +186,6 @@ void AArch64::ExtensionSet::enable(ArchExtKind E) { // Special cases for dependencies which vary depending on the base // architecture version. if (BaseArch) { - // +sve implies +f32mm if the base architecture is v8.6A+ or v9.1A+ - // It isn't the case in general that sve implies both f64mm and f32mm - if (E == AEK_SVE && BaseArch->is_superset(ARMV8_6A)) - enable(AEK_F32MM); - // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+ if (E == AEK_FP16 && BaseArch->is_superset(ARMV8_4A) && !BaseArch->is_superset(ARMV9A)) diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index a7d0b1687a7f..2c72a7229b52 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -2347,13 +2347,6 @@ AArch64ExtensionDependenciesBaseArchTestParams {}, {"aes", "sha2", "sha3", "sm4"}}, - // +sve implies +f32mm if the base architecture is v8.6A+ or v9.1A+, but - // not earlier architectures. - {AArch64::ARMV8_5A, {"sve"}, {"sve"}, {"f32mm"}}, - {AArch64::ARMV9A, {"sve"}, {"sve"}, {"f32mm"}}, - {AArch64::ARMV8_6A, {"sve"}, {"sve", "f32mm"}, {}}, - {AArch64::ARMV9_1A, {"sve"}, {"sve", "f32mm"}, {}}, - // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+ {AArch64::ARMV8_3A, {"fp16"}, {"fullfp16"}, {"fp16fml"}}, {AArch64::ARMV9A, {"fp16"}, {"fullfp16"}, {"fp16fml"}}, @@ -2520,10 +2513,10 @@ AArch64ExtensionDependenciesBaseCPUTestParams {}}, {"cortex-a520", {}, - {"v9.2a", "bf16", "crc", "dotprod", "f32mm", "flagm", - "fp-armv8", "fullfp16", "fp16fml", "i8mm", "lse", "mte", - "pauth", "perfmon", "predres", "ras", "rcpc", "rdm", - "sb", "neon", "ssbs", "sve", "sve2-bitperm", "sve2"}, + {"v9.2a", "bf16", "crc", "dotprod", "flagm", "fp-armv8", + "fullfp16", "fp16fml", "i8mm", "lse", "mte", "pauth", + "perfmon", "predres", "ras", "rcpc", "rdm", "sb", + "neon", "ssbs", "sve", "sve2-bitperm", "sve2"}, {}}, // Negative modifiers -- GitLab From 2938f1cff9f880d03c900a2bdcd078af937d9433 Mon Sep 17 00:00:00 2001 From: zhongyunde 00443407 Date: Sun, 24 Mar 2024 05:56:52 -0400 Subject: [PATCH 040/541] [InstCombine] Refactor powi(X,Y) / X to call foldPowiReassoc, NFC --- .../InstCombine/InstCombineMulDivRem.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index af238a43b11a..a9f0a16be0b8 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -611,6 +611,18 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { Y->getType() == Z->getType()) return createPowiExpr(I, *this, X, Y, Z); + // powi(X, Y) / X --> powi(X, Y-1) + // This is legal when (Y - 1) can't wraparound, in which case reassoc and nnan + // are required. + // TODO: Multi-use may be also better off creating Powi(x,y-1) + if (I.hasAllowReassoc() && I.hasNoNaNs() && + match(Op0, m_OneUse(m_Intrinsic(m_Specific(Op1), + m_Value(Y)))) && + willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) { + Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType()); + return createPowiExpr(I, *this, Op1, Y, NegOne); + } + return nullptr; } @@ -1904,20 +1916,8 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { return replaceInstUsesWith(I, Pow); } - // powi(X, Y) / X --> powi(X, Y-1) - // This is legal when (Y - 1) can't wraparound, in which case reassoc and nnan - // are required. - // TODO: Multi-use may be also better off creating Powi(x,y-1) - if (I.hasAllowReassoc() && I.hasNoNaNs() && - match(Op0, m_OneUse(m_Intrinsic(m_Specific(Op1), - m_Value(Y)))) && - willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) { - Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType()); - Value *Y1 = Builder.CreateAdd(Y, NegOne); - Type *Types[] = {Op1->getType(), Y1->getType()}; - Value *Pow = Builder.CreateIntrinsic(Intrinsic::powi, Types, {Op1, Y1}, &I); - return replaceInstUsesWith(I, Pow); - } + if (Instruction *FoldedPowi = foldPowiReassoc(I)) + return FoldedPowi; return nullptr; } -- GitLab From bd9bb31bce0754c0a04d5c842ab3e7f8dd467861 Mon Sep 17 00:00:00 2001 From: zhongyunde 00443407 Date: Sun, 24 Mar 2024 06:16:41 -0400 Subject: [PATCH 041/541] [InstCombine] add restrict reassoc for the powi(X,Y) / X add restrict reassoc for the powi(X,Y) / X according the discuss on PR69998. --- .../InstCombine/InstCombineMulDivRem.cpp | 4 ++-- llvm/test/Transforms/InstCombine/powi.ll | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index a9f0a16be0b8..8c698e52b5a0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -616,8 +616,8 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { // are required. // TODO: Multi-use may be also better off creating Powi(x,y-1) if (I.hasAllowReassoc() && I.hasNoNaNs() && - match(Op0, m_OneUse(m_Intrinsic(m_Specific(Op1), - m_Value(Y)))) && + match(Op0, m_OneUse(m_AllowReassoc(m_Intrinsic( + m_Specific(Op1), m_Value(Y))))) && willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) { Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType()); return createPowiExpr(I, *this, Op1, Y, NegOne); diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll index 43e34c889106..6c0575e8b719 100644 --- a/llvm/test/Transforms/InstCombine/powi.ll +++ b/llvm/test/Transforms/InstCombine/powi.ll @@ -313,7 +313,7 @@ define double @fdiv_pow_powi(double %x) { ; CHECK-NEXT: [[DIV:%.*]] = fmul reassoc nnan double [[X:%.*]], [[X]] ; CHECK-NEXT: ret double [[DIV]] ; - %p1 = call double @llvm.powi.f64.i32(double %x, i32 3) + %p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 3) %div = fdiv reassoc nnan double %p1, %x ret double %div } @@ -323,7 +323,7 @@ define float @fdiv_powf_powi(float %x) { ; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan float @llvm.powi.f32.i32(float [[X:%.*]], i32 99) ; CHECK-NEXT: ret float [[DIV]] ; - %p1 = call float @llvm.powi.f32.i32(float %x, i32 100) + %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100) %div = fdiv reassoc nnan float %p1, %x ret float %div } @@ -347,10 +347,21 @@ define double @fdiv_pow_powi_multi_use(double %x) { define float @fdiv_powf_powi_missing_reassoc(float %x) { ; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc( ; CHECK-NEXT: [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100) -; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float [[P1]], [[X]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan float [[P1]], [[X]] ; CHECK-NEXT: ret float [[DIV]] ; %p1 = call float @llvm.powi.f32.i32(float %x, i32 100) + %div = fdiv reassoc nnan float %p1, %x + ret float %div +} + +define float @fdiv_powf_powi_missing_reassoc1(float %x) { +; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc1( +; CHECK-NEXT: [[P1:%.*]] = call reassoc float @llvm.powi.f32.i32(float [[X:%.*]], i32 100) +; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float [[P1]], [[X]] +; CHECK-NEXT: ret float [[DIV]] +; + %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100) %div = fdiv nnan float %p1, %x ret float %div } -- GitLab From df75183d70e029352a49c93f275db703c81a65c1 Mon Sep 17 00:00:00 2001 From: Julian Nagele Date: Wed, 27 Mar 2024 09:30:27 +0000 Subject: [PATCH 042/541] [TBAA] Add verifier for tbaa.struct metadata (#86709) Adds logic to the IR verifier that checks whether !tbaa.struct nodes are well-formed. That is, it checks that the operands of !tbaa.struct nodes are in groups of three, that each group of three operands consists of two integers and a valid tbaa node, and that the regions described by the offset and size operands are non-overlapping. PR: https://github.com/llvm/llvm-project/pull/86709 --- llvm/include/llvm/IR/Verifier.h | 1 + llvm/lib/IR/Verifier.cpp | 32 +++++++++++++++++++ llvm/test/CodeGen/AArch64/arm64-abi_align.ll | 4 ++- .../AMDGPU/mem-intrinsics.ll | 2 +- .../InstCombine/struct-assign-tbaa.ll | 2 +- llvm/test/Transforms/SROA/tbaa-struct3.ll | 2 +- .../Scalarizer/basic-inseltpoison.ll | 3 +- llvm/test/Transforms/Scalarizer/basic.ll | 3 +- llvm/test/Verifier/tbaa-struct.ll | 14 ++++++-- 9 files changed, 54 insertions(+), 9 deletions(-) diff --git a/llvm/include/llvm/IR/Verifier.h b/llvm/include/llvm/IR/Verifier.h index b25f8eb77ee3..b7db6e0bbfb7 100644 --- a/llvm/include/llvm/IR/Verifier.h +++ b/llvm/include/llvm/IR/Verifier.h @@ -77,6 +77,7 @@ public: /// Visit an instruction and return true if it is valid, return false if an /// invalid TBAA is attached. bool visitTBAAMetadata(Instruction &I, const MDNode *MD); + bool visitTBAAStructMetadata(Instruction &I, const MDNode *MD); }; /// Check a function for errors, useful for use when debugging a diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 33f358440a31..e16572540f96 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5096,6 +5096,9 @@ void Verifier::visitInstruction(Instruction &I) { if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); + if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa_struct)) + TBAAVerifyHelper.visitTBAAStructMetadata(I, TBAA); + if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias)) visitAliasScopeListMetadata(MD); if (MDNode *MD = I.getMetadata(LLVMContext::MD_alias_scope)) @@ -7419,6 +7422,35 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { return true; } +bool TBAAVerifier::visitTBAAStructMetadata(Instruction &I, const MDNode *MD) { + CheckTBAA(MD->getNumOperands() % 3 == 0, + "tbaa.struct operands must occur in groups of three", &I, MD); + + // Each group of three operands must consist of two integers and a + // tbaa node. Moreover, the regions described by the offset and size + // operands must be non-overlapping. + std::optional NextFree; + for (unsigned int Idx = 0; Idx < MD->getNumOperands(); Idx += 3) { + auto *OffsetCI = + mdconst::dyn_extract_or_null(MD->getOperand(Idx)); + CheckTBAA(OffsetCI, "Offset must be a constant integer", &I, MD); + + auto *SizeCI = + mdconst::dyn_extract_or_null(MD->getOperand(Idx + 1)); + CheckTBAA(SizeCI, "Size must be a constant integer", &I, MD); + + MDNode *TBAA = dyn_cast_or_null(MD->getOperand(Idx + 2)); + CheckTBAA(TBAA, "TBAA tag missing", &I, MD); + visitTBAAMetadata(I, TBAA); + + bool NonOverlapping = !NextFree || NextFree->ule(OffsetCI->getValue()); + CheckTBAA(NonOverlapping, "Overlapping tbaa.struct regions", &I, MD); + + NextFree = OffsetCI->getValue() + SizeCI->getValue(); + } + return true; +} + char VerifierLegacyPass::ID = 0; INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false) diff --git a/llvm/test/CodeGen/AArch64/arm64-abi_align.ll b/llvm/test/CodeGen/AArch64/arm64-abi_align.ll index 089e171e5a4a..c9fd2d38e27a 100644 --- a/llvm/test/CodeGen/AArch64/arm64-abi_align.ll +++ b/llvm/test/CodeGen/AArch64/arm64-abi_align.ll @@ -518,4 +518,6 @@ attributes #5 = { nobuiltin } !1 = !{!"omnipotent char", !2} !2 = !{!"Simple C/C++ TBAA"} !3 = !{!"short", !1} -!4 = !{i64 0, i64 4, !0, i64 4, i64 2, !3, i64 8, i64 4, !0, i64 12, i64 2, !3, i64 16, i64 4, !0, i64 20, i64 2, !3} +!4 = !{i64 0, i64 4, !5, i64 4, i64 2, !6, i64 8, i64 4, !5, i64 12, i64 2, !6, i64 16, i64 4, !5, i64 20, i64 2, !6} +!5 = !{!0, !0, i64 0} +!6 = !{!3, !3, i64 0} diff --git a/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll index 50b0e7a0f547..2f264a2432fc 100644 --- a/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll +++ b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll @@ -141,4 +141,4 @@ attributes #1 = { argmemonly nounwind } !5 = distinct !{!5, !"some domain"} !6 = !{!7} !7 = distinct !{!7, !5, !"some scope 2"} -!8 = !{i64 0, i64 8, null} +!8 = !{i64 0, i64 8, !0} diff --git a/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll b/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll index 996d2c0e67e1..d079c03f1dcb 100644 --- a/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll +++ b/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll @@ -75,7 +75,7 @@ entry: !1 = !{!"omnipotent char", !0} !2 = !{!5, !5, i64 0} !3 = !{i64 0, i64 4, !2} -!4 = !{i64 0, i64 8, null} +!4 = !{i64 0, i64 8, !2} !5 = !{!"float", !0} !6 = !{i64 0, i64 4, !2, i64 4, i64 4, !2} !7 = !{i64 0, i64 2, !2, i64 4, i64 6, !2} diff --git a/llvm/test/Transforms/SROA/tbaa-struct3.ll b/llvm/test/Transforms/SROA/tbaa-struct3.ll index 0fcd787fef97..61034de81e4b 100644 --- a/llvm/test/Transforms/SROA/tbaa-struct3.ll +++ b/llvm/test/Transforms/SROA/tbaa-struct3.ll @@ -539,7 +539,7 @@ declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias !6 = !{!5, !5, i64 0} !7 = !{i64 0, i64 8, !6, i64 8, i64 4, !1} !8 = !{i64 0, i64 4, !1, i64 4, i64 8, !6} -!9 = !{i64 0, i64 8, !6, i64 4, i64 8, !1} +!9 = !{i64 0, i64 8, !6, i64 8, i64 8, !1} !10 = !{i64 0, i64 2, !1, i64 2, i64 2, !1} !11 = !{i64 0, i64 1, !1, i64 1, i64 3, !1} !12 = !{i64 0, i64 2, !1, i64 2, i64 6, !1} diff --git a/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll b/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll index bbcdcb6f5867..73ae66dd76c6 100644 --- a/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll +++ b/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll @@ -836,5 +836,6 @@ define <2 x i32> @f23_crash(<2 x i32> %srcvec, i32 %v1) { !2 = !{ !"set2", !0 } !3 = !{ !3, !{!"llvm.loop.parallel_accesses", !13} } !4 = !{ float 4.0 } -!5 = !{ i64 0, i64 8, null } +!5 = !{ i64 0, i64 8, !6 } +!6 = !{ !1, !1, i64 0 } !13 = distinct !{} diff --git a/llvm/test/Transforms/Scalarizer/basic.ll b/llvm/test/Transforms/Scalarizer/basic.ll index db7c5f535f7e..87a70ccd3fc7 100644 --- a/llvm/test/Transforms/Scalarizer/basic.ll +++ b/llvm/test/Transforms/Scalarizer/basic.ll @@ -870,5 +870,6 @@ define <2 x float> @f25(<2 x float> %src) { !2 = !{ !"set2", !0 } !3 = !{ !3, !{!"llvm.loop.parallel_accesses", !13} } !4 = !{ float 4.0 } -!5 = !{ i64 0, i64 8, null } +!5 = !{ i64 0, i64 8, !6 } +!6 = !{ !1, !1, i64 0 } !13 = distinct !{} diff --git a/llvm/test/Verifier/tbaa-struct.ll b/llvm/test/Verifier/tbaa-struct.ll index b8ddc7cee496..14c19a19d5ae 100644 --- a/llvm/test/Verifier/tbaa-struct.ll +++ b/llvm/test/Verifier/tbaa-struct.ll @@ -1,28 +1,36 @@ -; RUN: llvm-as < %s 2>&1 - -; FIXME: The verifer should reject the invalid !tbaa.struct nodes below. +; RUN: not llvm-as < %s 2>&1 | FileCheck %s define void @test_overlapping_regions(ptr %a1) { +; CHECK: Overlapping tbaa.struct regions +; CHECK-NEXT: %ld = load i8, ptr %a1, align 1, !tbaa.struct !0 %ld = load i8, ptr %a1, align 1, !tbaa.struct !0 ret void } define void @test_size_not_integer(ptr %a1) { +; CHECK: Size must be a constant integer +; CHECK-NEXT: store i8 1, ptr %a1, align 1, !tbaa.struct !5 store i8 1, ptr %a1, align 1, !tbaa.struct !5 ret void } define void @test_offset_not_integer(ptr %a1, ptr %a2) { +; CHECK: Offset must be a constant integer +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !6 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !6 ret void } define void @test_tbaa_missing(ptr %a1, ptr %a2) { +; CHECK: TBAA tag missing +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !7 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !7 ret void } define void @test_tbaa_invalid(ptr %a1) { +; CHECK: Old-style TBAA is no longer allowed, use struct-path TBAA instead +; CHECK-NEXT: store i8 1, ptr %a1, align 1, !tbaa.struct !8 store i8 1, ptr %a1, align 1, !tbaa.struct !8 ret void } -- GitLab From f15b7deeaaf9028a31f66110a10f1313ed5e57f7 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 27 Mar 2024 17:40:44 +0800 Subject: [PATCH 043/541] [RISCV] Add test case to show missing vmerge fold on tied pseudos. NFC Note we can't use vwaddu.wv because it will get combined away with #78403 --- .../RISCV/rvv/rvv-peephole-vmerge-vops.ll | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll index a4aef577bc9a..571e2df13c26 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll @@ -1187,3 +1187,19 @@ define @vmerge_larger_vl_false_becomes_tail( @llvm.riscv.vmerge.nxv2i32.nxv2i32( poison, %false, %a, %m, i64 3) ret %b } + +; Test widening pseudos with their TIED variant (passthru same as first op). +define @vpmerge_vwsub.w_tied( %passthru, %x, %y, %mask, i32 zeroext %vl) { +; CHECK-LABEL: vpmerge_vwsub.w_tied: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a0, e32, m1, tu, ma +; CHECK-NEXT: vmv2r.v v10, v8 +; CHECK-NEXT: vwsub.wv v10, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, tu, ma +; CHECK-NEXT: vmerge.vvm v8, v8, v10, v0 +; CHECK-NEXT: ret + %vl.zext = zext i32 %vl to i64 + %a = call @llvm.riscv.vwsub.w.nxv2i64.nxv2i32( %passthru, %passthru, %y, i64 %vl.zext) + %b = call @llvm.vp.merge.nxv2i64( %mask, %a, %passthru, i32 %vl) + ret %b +} -- GitLab From cc23ee8250c2eda3f28c4d25c412e68ec78ecbe1 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 27 Mar 2024 11:37:02 +0100 Subject: [PATCH 044/541] [LLD][COFF] Add support for EXPORTAS import name type. (#86541) #78772 added similar support for .def file parser and import library writer. This PR adds missing bits in LLD to propagate EXPORTAS name and allow it in `/export` parser. This is syntax is used by MSVC for ARM64EC `__declspec(dllexport)` handling. --- lld/COFF/Config.h | 8 ++-- lld/COFF/Driver.cpp | 2 + lld/COFF/DriverUtils.cpp | 14 +++++- lld/test/COFF/exportas.test | 88 +++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 6 deletions(-) diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 8f85929f1bea..917f88fc2828 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -54,6 +54,7 @@ enum class EmitKind { Obj, LLVM, ASM }; struct Export { StringRef name; // N in /export:N or /export:E=N StringRef extName; // E in /export:E=N + StringRef exportAs; // E in /export:N,EXPORTAS,E StringRef aliasTarget; // GNU specific: N in "alias == N" Symbol *sym = nullptr; uint16_t ordinal = 0; @@ -73,10 +74,9 @@ struct Export { StringRef exportName; // Name in DLL bool operator==(const Export &e) const { - return (name == e.name && extName == e.extName && - aliasTarget == e.aliasTarget && - ordinal == e.ordinal && noname == e.noname && - data == e.data && isPrivate == e.isPrivate); + return (name == e.name && extName == e.extName && exportAs == e.exportAs && + aliasTarget == e.aliasTarget && ordinal == e.ordinal && + noname == e.noname && data == e.data && isPrivate == e.isPrivate); } }; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 181492913c0d..2b1d4abb6ed0 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -945,6 +945,7 @@ void LinkerDriver::createImportLibrary(bool asLib) { e2.Name = std::string(e1.name); e2.SymbolName = std::string(e1.symbolName); e2.ExtName = std::string(e1.extName); + e2.ExportAs = std::string(e1.exportAs); e2.AliasTarget = std::string(e1.aliasTarget); e2.Ordinal = e1.ordinal; e2.Noname = e1.noname; @@ -1044,6 +1045,7 @@ void LinkerDriver::parseModuleDefs(StringRef path) { e2.name = saver().save(e1.Name); e2.extName = saver().save(e1.ExtName); } + e2.exportAs = saver().save(e1.ExportAs); e2.aliasTarget = saver().save(e1.AliasTarget); e2.ordinal = e1.Ordinal; e2.noname = e1.Noname; diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 0fa4769bab19..b4ff31a606da 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -585,7 +585,8 @@ Export LinkerDriver::parseExport(StringRef arg) { } } - // Optional parameters "[,@ordinal[,NONAME]][,DATA][,PRIVATE]" + // Optional parameters + // "[,@ordinal[,NONAME]][,DATA][,PRIVATE][,EXPORTAS,exportname]" while (!rest.empty()) { StringRef tok; std::tie(tok, rest) = rest.split(","); @@ -607,6 +608,13 @@ Export LinkerDriver::parseExport(StringRef arg) { e.isPrivate = true; continue; } + if (tok.equals_insensitive("exportas")) { + if (!rest.empty() && !rest.contains(',')) + e.exportAs = rest; + else + error("invalid EXPORTAS value: " + rest); + break; + } if (tok.starts_with("@")) { int32_t ord; if (tok.substr(1).getAsInteger(0, ord)) @@ -683,7 +691,9 @@ void LinkerDriver::fixupExports() { } for (Export &e : ctx.config.exports) { - if (!e.forwardTo.empty()) { + if (!e.exportAs.empty()) { + e.exportName = e.exportAs; + } else if (!e.forwardTo.empty()) { e.exportName = undecorate(ctx, e.name); } else { e.exportName = undecorate(ctx, e.extName.empty() ? e.name : e.extName); diff --git a/lld/test/COFF/exportas.test b/lld/test/COFF/exportas.test index c0295c3d7fb7..d70547c39b40 100644 --- a/lld/test/COFF/exportas.test +++ b/lld/test/COFF/exportas.test @@ -9,6 +9,77 @@ RUN: lld-link -out:out1.dll -dll -noentry test.obj test.lib RUN: llvm-readobj --coff-imports out1.dll | FileCheck --check-prefix=IMPORT %s IMPORT: Symbol: expfunc +Pass -export argument with EXPORTAS. + +RUN: llvm-mc -filetype=obj -triple=x86_64-windows func.s -o func.obj +RUN: lld-link -out:out2.dll -dll -noentry func.obj -export:func,EXPORTAS,expfunc +RUN: llvm-readobj --coff-exports out2.dll | FileCheck --check-prefix=EXPORT %s +EXPORT: Name: expfunc + +RUN: llvm-readobj out2.lib | FileCheck --check-prefix=IMPLIB %s +IMPLIB: Name type: export as +IMPLIB-NEXT: Export name: expfunc +IMPLIB-NEXT: Symbol: __imp_func +IMPLIB-NEXT: Symbol: func + +Use .drectve section with EXPORTAS. + +RUN: llvm-mc -filetype=obj -triple=x86_64-windows drectve.s -o drectve.obj +RUN: lld-link -out:out3.dll -dll -noentry func.obj drectve.obj +RUN: llvm-readobj --coff-exports out3.dll | FileCheck --check-prefix=EXPORT %s +RUN: llvm-readobj out3.lib | FileCheck --check-prefix=IMPLIB %s + +Use a .def file with EXPORTAS. + +RUN: lld-link -out:out4.dll -dll -noentry func.obj -def:test.def +RUN: llvm-readobj --coff-exports out4.dll | FileCheck --check-prefix=EXPORT %s +RUN: llvm-readobj out4.lib | FileCheck --check-prefix=IMPLIB %s + +Use a .def file with EXPORTAS in a forwarding export. + +RUN: lld-link -out:out5.dll -dll -noentry func.obj -def:test2.def +RUN: llvm-readobj --coff-exports out5.dll | FileCheck --check-prefix=FORWARD-EXPORT %s +FORWARD-EXPORT: Export { +FORWARD-EXPORT-NEXT: Ordinal: 1 +FORWARD-EXPORT-NEXT: Name: expfunc +FORWARD-EXPORT-NEXT: ForwardedTo: otherdll.otherfunc +FORWARD-EXPORT-NEXT: } + +RUN: llvm-readobj out5.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s +FORWARD-IMPLIB: Name type: export as +FORWARD-IMPLIB-NEXT: Export name: expfunc +FORWARD-IMPLIB-NEXT: Symbol: __imp_func +FORWARD-IMPLIB-NEXT: Symbol: func + +Pass -export argument with EXPORTAS in a forwarding export. + +RUN: lld-link -out:out6.dll -dll -noentry func.obj -export:func=otherdll.otherfunc,EXPORTAS,expfunc +RUN: llvm-readobj --coff-exports out6.dll | FileCheck --check-prefix=FORWARD-EXPORT %s +RUN: llvm-readobj out6.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s + +Pass -export argument with EXPORTAS in a data export. + +RUN: lld-link -out:out7.dll -dll -noentry func.obj -export:func,DATA,@5,EXPORTAS,expfunc +RUN: llvm-readobj --coff-exports out7.dll | FileCheck --check-prefix=ORD %s +ORD: Ordinal: 5 +ORD-NEXT: Name: expfunc + +RUN: llvm-readobj out7.lib | FileCheck --check-prefix=ORD-IMPLIB %s +ORD-IMPLIB: Type: data +ORD-IMPLIB-NEXT: Name type: export as +ORD-IMPLIB-NEXT: Export name: expfunc +ORD-IMPLIB-NEXT: Symbol: __imp_func + +Check invalid EXPORTAS syntax. + +RUN: not lld-link -out:err1.dll -dll -noentry func.obj -export:func,EXPORTAS, 2>&1 | \ +RUN: FileCheck --check-prefix=ERR1 %s +ERR1: error: invalid EXPORTAS value: {{$}} + +RUN: not lld-link -out:err2.dll -dll -noentry func.obj -export:func,EXPORTAS,expfunc,DATA 2>&1 | \ +RUN: FileCheck --check-prefix=ERR2 %s +ERR2: error: invalid EXPORTAS value: expfunc,DATA + #--- test.s .section ".test", "rd" .rva __imp_func @@ -17,3 +88,20 @@ IMPORT: Symbol: expfunc LIBRARY test.dll EXPORTS func EXPORTAS expfunc + +#--- test2.def +LIBRARY test.dll +EXPORTS + func=otherdll.otherfunc EXPORTAS expfunc + +#--- func.s + .text + .globl func + .p2align 2, 0x0 +func: + movl $1, %eax + retq + +#--- drectve.s + .section .drectve, "yn" + .ascii " -export:func,EXPORTAS,expfunc" -- GitLab From c9d12664f2f967ec170ed16d9a57af2f48e832c8 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 27 Mar 2024 11:41:02 +0100 Subject: [PATCH 045/541] [llvm-dlltool][llvm-lib][COFF] Don't override NONAME exports with demangled ARM64EC symbols. (#86722) --- llvm/lib/Object/COFFImportFile.cpp | 4 +- llvm/test/tools/llvm-lib/arm64ec-implib.test | 93 ++++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index 8224a1492502..477c5bf98249 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -690,12 +690,12 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, if (ImportType == IMPORT_CODE && isArm64EC(M)) { if (std::optional MangledName = getArm64ECMangledFunctionName(Name)) { - if (ExportName.empty()) { + if (!E.Noname && ExportName.empty()) { NameType = IMPORT_NAME_EXPORTAS; ExportName.swap(Name); } Name = std::move(*MangledName); - } else if (ExportName.empty()) { + } else if (!E.Noname && ExportName.empty()) { NameType = IMPORT_NAME_EXPORTAS; ExportName = std::move(*getArm64ECDemangledFunctionName(Name)); } diff --git a/llvm/test/tools/llvm-lib/arm64ec-implib.test b/llvm/test/tools/llvm-lib/arm64ec-implib.test index 9ce53fe0fea0..e9987d0ca2e6 100644 --- a/llvm/test/tools/llvm-lib/arm64ec-implib.test +++ b/llvm/test/tools/llvm-lib/arm64ec-implib.test @@ -14,6 +14,8 @@ ARMAP-NEXT: Archive EC map ARMAP-NEXT: #expname in test.dll ARMAP-NEXT: #funcexp in test.dll ARMAP-NEXT: #mangledfunc in test.dll +ARMAP-NEXT: #manglednonamefunc in test.dll +ARMAP-NEXT: #nonamefunc in test.dll ARMAP-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll ARMAP-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll @@ -23,13 +25,19 @@ ARMAP-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __imp_aux_expname in test.dll ARMAP-NEXT: __imp_aux_funcexp in test.dll ARMAP-NEXT: __imp_aux_mangledfunc in test.dll +ARMAP-NEXT: __imp_aux_manglednonamefunc in test.dll +ARMAP-NEXT: __imp_aux_nonamefunc in test.dll ARMAP-NEXT: __imp_dataexp in test.dll ARMAP-NEXT: __imp_expname in test.dll ARMAP-NEXT: __imp_funcexp in test.dll ARMAP-NEXT: __imp_mangledfunc in test.dll +ARMAP-NEXT: __imp_manglednonamefunc in test.dll +ARMAP-NEXT: __imp_nonamefunc in test.dll ARMAP-NEXT: expname in test.dll ARMAP-NEXT: funcexp in test.dll ARMAP-NEXT: mangledfunc in test.dll +ARMAP-NEXT: manglednonamefunc in test.dll +ARMAP-NEXT: nonamefunc in test.dll ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-readobj test.lib | FileCheck -check-prefix=READOBJ %s @@ -95,6 +103,25 @@ READOBJ-NEXT: Type: data READOBJ-NEXT: Name type: name READOBJ-NEXT: Export name: dataexp READOBJ-NEXT: Symbol: __imp_dataexp +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-ARM64EC +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: ordinal +READOBJ-NEXT: Symbol: __imp_nonamefunc +READOBJ-NEXT: Symbol: nonamefunc +READOBJ-NEXT: Symbol: __imp_aux_nonamefunc +READOBJ-NEXT: Symbol: #nonamefunc +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-ARM64EC +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: ordinal +READOBJ-NEXT: Symbol: __imp_manglednonamefunc +READOBJ-NEXT: Symbol: manglednonamefunc +READOBJ-NEXT: Symbol: __imp_aux_manglednonamefunc +READOBJ-NEXT: Symbol: #manglednonamefunc + Using -machine:arm64x gives the same output. RUN: llvm-lib -machine:arm64x -def:test.def -out:testx.lib @@ -112,22 +139,28 @@ RUN: llvm-nm --print-armap testx.lib | FileCheck -check-prefix=ARMAPX %s ARMAPX: Archive map ARMAPX-NEXT: #mangledfunc in test.dll +ARMAPX-NEXT: #manglednonamefunc in test.dll ARMAPX-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __IMPORT_DESCRIPTOR_test in test.dll ARMAPX-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAPX-NEXT: __imp_#mangledfunc in test.dll +ARMAPX-NEXT: __imp_#manglednonamefunc in test.dll ARMAPX-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_dataexp in test.dll ARMAPX-NEXT: __imp_expname in test.dll ARMAPX-NEXT: __imp_funcexp in test.dll +ARMAPX-NEXT: __imp_nonamefunc in test.dll ARMAPX-NEXT: expname in test.dll ARMAPX-NEXT: funcexp in test.dll +ARMAPX-NEXT: nonamefunc in test.dll ARMAPX-NEXT: test_NULL_THUNK_DATA in test.dll ARMAPX-EMPTY: ARMAPX-NEXT: Archive EC map ARMAPX-NEXT: #expname in test.dll ARMAPX-NEXT: #funcexp in test.dll ARMAPX-NEXT: #mangledfunc in test.dll +ARMAPX-NEXT: #manglednonamefunc in test.dll +ARMAPX-NEXT: #nonamefunc in test.dll ARMAPX-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll ARMAPX-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __IMPORT_DESCRIPTOR_test in test.dll @@ -137,13 +170,19 @@ ARMAPX-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_aux_expname in test.dll ARMAPX-NEXT: __imp_aux_funcexp in test.dll ARMAPX-NEXT: __imp_aux_mangledfunc in test.dll +ARMAPX-NEXT: __imp_aux_manglednonamefunc in test.dll +ARMAPX-NEXT: __imp_aux_nonamefunc in test.dll ARMAPX-NEXT: __imp_dataexp in test.dll ARMAPX-NEXT: __imp_expname in test.dll ARMAPX-NEXT: __imp_funcexp in test.dll ARMAPX-NEXT: __imp_mangledfunc in test.dll +ARMAPX-NEXT: __imp_manglednonamefunc in test.dll +ARMAPX-NEXT: __imp_nonamefunc in test.dll ARMAPX-NEXT: expname in test.dll ARMAPX-NEXT: funcexp in test.dll ARMAPX-NEXT: mangledfunc in test.dll +ARMAPX-NEXT: manglednonamefunc in test.dll +ARMAPX-NEXT: nonamefunc in test.dll ARMAPX-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-readobj testx.lib | FileCheck -check-prefix=READOBJX %s @@ -211,6 +250,24 @@ READOBJX-NEXT: Export name: dataexp READOBJX-NEXT: Symbol: __imp_dataexp READOBJX-EMPTY: READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64EC +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_nonamefunc +READOBJX-NEXT: Symbol: nonamefunc +READOBJX-NEXT: Symbol: __imp_aux_nonamefunc +READOBJX-NEXT: Symbol: #nonamefunc +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64EC +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_manglednonamefunc +READOBJX-NEXT: Symbol: manglednonamefunc +READOBJX-NEXT: Symbol: __imp_aux_manglednonamefunc +READOBJX-NEXT: Symbol: #manglednonamefunc +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll READOBJX-NEXT: Format: COFF-import-file-ARM64 READOBJX-NEXT: Type: code READOBJX-NEXT: Name type: name @@ -248,6 +305,20 @@ READOBJX-NEXT: Type: data READOBJX-NEXT: Name type: name READOBJX-NEXT: Export name: dataexp READOBJX-NEXT: Symbol: __imp_dataexp +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64 +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_nonamefunc +READOBJX-NEXT: Symbol: nonamefunc +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64 +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_#manglednonamefunc +READOBJX-NEXT: Symbol: #manglednonamefunc RUN: llvm-lib -machine:arm64ec -def:test.def -defArm64Native:test2.def -out:test2.lib @@ -266,6 +337,8 @@ ARMAPX2-NEXT: Archive EC map ARMAPX2-NEXT: #expname in test2.dll ARMAPX2-NEXT: #funcexp in test2.dll ARMAPX2-NEXT: #mangledfunc in test2.dll +ARMAPX2-NEXT: #manglednonamefunc in test2.dll +ARMAPX2-NEXT: #nonamefunc in test2.dll ARMAPX2-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test2.dll ARMAPX2-NEXT: ?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __IMPORT_DESCRIPTOR_test2 in test2.dll @@ -275,13 +348,19 @@ ARMAPX2-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __imp_aux_expname in test2.dll ARMAPX2-NEXT: __imp_aux_funcexp in test2.dll ARMAPX2-NEXT: __imp_aux_mangledfunc in test2.dll +ARMAPX2-NEXT: __imp_aux_manglednonamefunc in test2.dll +ARMAPX2-NEXT: __imp_aux_nonamefunc in test2.dll ARMAPX2-NEXT: __imp_dataexp in test2.dll ARMAPX2-NEXT: __imp_expname in test2.dll ARMAPX2-NEXT: __imp_funcexp in test2.dll ARMAPX2-NEXT: __imp_mangledfunc in test2.dll +ARMAPX2-NEXT: __imp_manglednonamefunc in test2.dll +ARMAPX2-NEXT: __imp_nonamefunc in test2.dll ARMAPX2-NEXT: expname in test2.dll ARMAPX2-NEXT: funcexp in test2.dll ARMAPX2-NEXT: mangledfunc in test2.dll +ARMAPX2-NEXT: manglednonamefunc in test2.dll +ARMAPX2-NEXT: nonamefunc in test2.dll ARMAPX2-NEXT: test2_NULL_THUNK_DATA in test2.dll ARMAPX2: test2.dll: @@ -312,6 +391,18 @@ ARMAPX2-NEXT: test2.dll: ARMAPX2-NEXT: 00000000 D __imp_dataexp ARMAPX2-EMPTY: ARMAPX2-NEXT: test2.dll: +ARMAPX2-NEXT: 00000000 T #nonamefunc +ARMAPX2-NEXT: 00000000 T __imp_aux_nonamefunc +ARMAPX2-NEXT: 00000000 T __imp_nonamefunc +ARMAPX2-NEXT: 00000000 T nonamefunc +ARMAPX2-EMPTY: +ARMAPX2-NEXT: test2.dll: +ARMAPX2-NEXT: 00000000 T #manglednonamefunc +ARMAPX2-NEXT: 00000000 T __imp_aux_manglednonamefunc +ARMAPX2-NEXT: 00000000 T __imp_manglednonamefunc +ARMAPX2-NEXT: 00000000 T manglednonamefunc +ARMAPX2-EMPTY: +ARMAPX2-NEXT: test2.dll: ARMAPX2-NEXT: 00000000 T __imp_otherfunc ARMAPX2-NEXT: 00000000 T otherfunc @@ -406,6 +497,8 @@ EXPORTS ?test_cpp_func@@YAHPEAX@Z expname=impname dataexp DATA + nonamefunc @1 NONAME + #manglednonamefunc @2 NONAME #--- test2.def LIBRARY test2.dll -- GitLab From ab7dba233a058cc8310ef829929238b5d8440b30 Mon Sep 17 00:00:00 2001 From: Alex Voicu Date: Wed, 27 Mar 2024 13:41:34 +0200 Subject: [PATCH 046/541] [CodeGen][LLVM] Make the `va_list` related intrinsics generic. (#85460) Currently, the builtins used for implementing `va_list` handling unconditionally take their arguments as unqualified `ptr`s i.e. pointers to AS 0. This does not work for targets where the default AS is not 0 or AS 0 is not a viable AS (for example, a target might choose 0 to represent the constant address space). This patch changes the builtins' signature to take generic `anyptr` args, which corrects this issue. It is noisy due to the number of tests affected. A test for an upstream target which does not use 0 as its default AS (SPIRV for HIP device compilations) is added as well. --- clang/lib/CodeGen/CGBuiltin.cpp | 6 ++- clang/test/CodeGen/CSKY/csky-abi.c | 16 +++---- clang/test/CodeGen/LoongArch/abi-lp64d.c | 4 +- .../test/CodeGen/PowerPC/aix-altivec-vaargs.c | 4 +- clang/test/CodeGen/PowerPC/aix-vaargs.c | 14 +++--- .../CodeGen/PowerPC/ppc64le-varargs-f128.c | 18 +++---- clang/test/CodeGen/RISCV/riscv32-vararg.c | 40 ++++++++-------- clang/test/CodeGen/RISCV/riscv64-vararg.c | 16 +++---- clang/test/CodeGen/WebAssembly/wasm-varargs.c | 16 +++---- clang/test/CodeGen/X86/va-arg-sse.c | 4 +- clang/test/CodeGen/X86/x86_64-vaarg.c | 4 +- clang/test/CodeGen/aarch64-ABI-align-packed.c | 14 +++--- clang/test/CodeGen/aarch64-varargs.c | 2 +- clang/test/CodeGen/arm-varargs.c | 2 +- clang/test/CodeGen/hexagon-linux-vararg.c | 2 +- clang/test/CodeGen/mips-varargs.c | 16 +++---- clang/test/CodeGen/pr53127.cpp | 4 +- ...rargs-with-nonzero-default-address-space.c | 46 ++++++++++++++++++ clang/test/CodeGen/xcore-abi.c | 2 +- clang/test/CodeGenCXX/ext-int.cpp | 12 ++--- clang/test/CodeGenCXX/ibm128-declarations.cpp | 4 +- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 4 +- clang/test/Modules/codegen.test | 2 +- llvm/docs/LangRef.rst | 29 ++++++----- llvm/include/llvm/IR/Intrinsics.td | 11 +++-- llvm/test/Bitcode/compatibility-3.6.ll | 16 +++---- llvm/test/Bitcode/compatibility-3.7.ll | 16 +++---- llvm/test/Bitcode/compatibility-3.8.ll | 16 +++---- llvm/test/Bitcode/compatibility-3.9.ll | 16 +++---- llvm/test/Bitcode/compatibility-4.0.ll | 16 +++---- llvm/test/Bitcode/compatibility-5.0.ll | 16 +++---- llvm/test/Bitcode/compatibility-6.0.ll | 16 +++---- llvm/test/Bitcode/compatibility.ll | 18 +++---- llvm/test/Bitcode/thinlto-function-summary.ll | 6 +-- .../Bitcode/variableArgumentIntrinsic.3.2.ll | 8 ++-- .../MemorySanitizer/AArch64/vararg_shadow.ll | 48 +++++++++---------- .../MemorySanitizer/SystemZ/vararg-kernel.ll | 2 +- .../MemorySanitizer/X86/vararg_shadow.ll | 48 +++++++++---------- .../MemorySanitizer/msan_debug_info.ll | 2 +- .../Transforms/GlobalOpt/inalloca-varargs.ll | 2 +- .../Transforms/IROutliner/illegal-vaarg.ll | 12 ++--- .../IROutliner/outline-vaarg-intrinsic.ll | 8 ++-- llvm/test/Transforms/NewGVN/pr31483.ll | 2 +- .../Transforms/Reassociate/vaarg_movable.ll | 4 +- .../mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td | 6 +-- mlir/test/Target/LLVMIR/Import/basic.ll | 14 +++--- mlir/test/Target/LLVMIR/Import/intrinsic.ll | 12 ++--- mlir/test/Target/LLVMIR/llvmir.mlir | 8 ++-- 48 files changed, 330 insertions(+), 274 deletions(-) create mode 100644 clang/test/CodeGen/varargs-with-nonzero-default-address-space.c diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3cfdb261a0ea..fdb517eb254d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -792,7 +792,8 @@ EncompassingIntegerType(ArrayRef Types) { Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) { Intrinsic::ID inst = IsStart ? Intrinsic::vastart : Intrinsic::vaend; - return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue); + return Builder.CreateCall(CGM.getIntrinsic(inst, {ArgValue->getType()}), + ArgValue); } /// Checks if using the result of __builtin_object_size(p, @p From) in place of @@ -3018,7 +3019,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_va_copy: { Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer(); Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer(); - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy), {DstPtr, SrcPtr}); + Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy, {DstPtr->getType()}), + {DstPtr, SrcPtr}); return RValue::get(nullptr); } case Builtin::BIabs: diff --git a/clang/test/CodeGen/CSKY/csky-abi.c b/clang/test/CodeGen/CSKY/csky-abi.c index 2e549376ba93..29ed661aea75 100644 --- a/clang/test/CodeGen/CSKY/csky-abi.c +++ b/clang/test/CodeGen/CSKY/csky-abi.c @@ -185,13 +185,13 @@ void f_va_caller(void) { // CHECK: [[VA:%.*]] = alloca ptr, align 4 // CHECK: [[V:%.*]] = alloca i32, align 4 // CHECK: store ptr %fmt, ptr [[FMT_ADDR]], align 4 -// CHECK: call void @llvm.va_start(ptr [[VA]]) +// CHECK: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK: [[TMP1:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK: store i32 [[TMP1]], ptr [[V]], align 4 -// CHECK: call void @llvm.va_end(ptr [[VA]]) +// CHECK: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK: [[TMP2:%.*]] = load i32, ptr [[V]], align 4 // CHECK: ret i32 [[TMP2]] // CHECK: } @@ -210,13 +210,13 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca double, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store double [[TMP4]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 4 // CHECK-NEXT: ret double [[TMP5]] double f_va_2(char *fmt, ...) { @@ -236,7 +236,7 @@ double f_va_2(char *fmt, ...) { // CHECK-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[X:%.*]] = alloca double, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -252,7 +252,7 @@ double f_va_2(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT5]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP11:%.*]] = load double, ptr [[ARGP_CUR4]], align 4 // CHECK-NEXT: store double [[TMP11]], ptr [[X]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP12:%.*]] = load double, ptr [[V]], align 4 // CHECK-NEXT: [[TMP13:%.*]] = load double, ptr [[X]], align 4 // CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP12]], [[TMP13]] @@ -279,7 +279,7 @@ double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -302,7 +302,7 @@ double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[ARGP_NEXT9:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR8]], i32 16 // CHECK-NEXT: store ptr [[ARGP_NEXT9]], ptr [[VA]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[ARGP_CUR8]], i32 16, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) int f_va_4(char *fmt, ...) { __builtin_va_list va; diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d.c b/clang/test/CodeGen/LoongArch/abi-lp64d.c index 66b480a7f068..fc7f1eada586 100644 --- a/clang/test/CodeGen/LoongArch/abi-lp64d.c +++ b/clang/test/CodeGen/LoongArch/abi-lp64d.c @@ -449,13 +449,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] int f_va_int(char *fmt, ...) { diff --git a/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c b/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c index 03182423a422..b3f1e93b6394 100644 --- a/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c +++ b/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c @@ -17,7 +17,7 @@ vector double vector_varargs(int count, ...) { } // CHECK: %arg_list = alloca ptr -// CHECK: call void @llvm.va_start(ptr %arg_list) +// CHECK: call void @llvm.va_start.p0(ptr %arg_list) // AIX32: for.body: // AIX32-NEXT: %argp.cur = load ptr, ptr %arg_list, align 4 @@ -41,4 +41,4 @@ vector double vector_varargs(int count, ...) { // CHECK: for.end: -// CHECK: call void @llvm.va_end(ptr %arg_list) +// CHECK: call void @llvm.va_end.p0(ptr %arg_list) diff --git a/clang/test/CodeGen/PowerPC/aix-vaargs.c b/clang/test/CodeGen/PowerPC/aix-vaargs.c index 8b8417d315a5..724ba6560cdb 100644 --- a/clang/test/CodeGen/PowerPC/aix-vaargs.c +++ b/clang/test/CodeGen/PowerPC/aix-vaargs.c @@ -35,7 +35,7 @@ void testva (int n, ...) { // CHECK-NEXT: %v = alloca i32, align 4 // CHECK-NEXT: store i32 %n, ptr %n.addr, align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr %ap) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr %ap) // AIX32-NEXT: %argp.cur = load ptr, ptr %ap, align 4 // AIX32-NEXT: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 16 @@ -48,7 +48,7 @@ void testva (int n, ...) { // AIX32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 %t, ptr align 4 %argp.cur, i32 16, i1 false) // AIX64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %t, ptr align 8 %argp.cur, i64 16, i1 false) -// CHECK-NEXT: call void @llvm.va_copy(ptr %ap2, ptr %ap) +// CHECK-NEXT: call void @llvm.va_copy.p0(ptr %ap2, ptr %ap) // AIX32-NEXT: %argp.cur1 = load ptr, ptr %ap2, align 4 // AIX32-NEXT: %argp.next2 = getelementptr inbounds i8, ptr %argp.cur1, i32 4 @@ -62,14 +62,14 @@ void testva (int n, ...) { // AIX64-NEXT: %1 = load i32, ptr %0, align 4 // AIX64-NEXT: store i32 %1, ptr %v, align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr %ap2) -// CHECK-NEXT: call void @llvm.va_end(ptr %ap) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap2) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap) // CHECK-NEXT: ret void -// CHECK: declare void @llvm.va_start(ptr) +// CHECK: declare void @llvm.va_start.p0(ptr) // AIX32: declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) // AIX64: declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) -// CHECK: declare void @llvm.va_copy(ptr, ptr) -// CHECK: declare void @llvm.va_end(ptr) +// CHECK: declare void @llvm.va_copy.p0(ptr, ptr) +// CHECK: declare void @llvm.va_end.p0(ptr) diff --git a/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c b/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c index 396614fe5bac..2f5459d1bb9c 100644 --- a/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c +++ b/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c @@ -31,7 +31,7 @@ void foo_ls(ldbl128_s); // OMP-TARGET: call void @foo_ld(ppc_fp128 noundef %[[V3]]) // OMP-HOST-LABEL: define{{.*}} void @omp( -// OMP-HOST: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// OMP-HOST: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // OMP-HOST: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]], align 8 // OMP-HOST: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // OMP-HOST: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -49,13 +49,13 @@ void omp(int n, ...) { } // IEEE-LABEL: define{{.*}} void @f128 -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16 // IEEE: call void @foo_fq(fp128 noundef %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) void f128(int n, ...) { va_list ap; va_start(ap, n); @@ -64,20 +64,20 @@ void f128(int n, ...) { } // IEEE-LABEL: define{{.*}} void @long_double -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16 // IEEE: call void @foo_ld(fp128 noundef %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) // IBM-LABEL: define{{.*}} void @long_double -// IBM: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IBM: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IBM: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IBM: %[[V4:[0-9a-zA-Z_.]+]] = load ppc_fp128, ptr %[[CUR]], align 8 // IBM: call void @foo_ld(ppc_fp128 noundef %[[V4]]) -// IBM: call void @llvm.va_end(ptr %[[AP]]) +// IBM: call void @llvm.va_end.p0(ptr %[[AP]]) void long_double(int n, ...) { va_list ap; va_start(ap, n); @@ -86,7 +86,7 @@ void long_double(int n, ...) { } // IEEE-LABEL: define{{.*}} void @long_double_struct -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -96,7 +96,7 @@ void long_double(int n, ...) { // IEEE: %[[COERCE:[0-9a-zA-Z_.]+]] = getelementptr inbounds %struct.ldbl128_s, ptr %[[TMP]], i32 0, i32 0 // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[COERCE]], align 16 // IEEE: call void @foo_ls(fp128 inreg %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) void long_double_struct(int n, ...) { va_list ap; va_start(ap, n); diff --git a/clang/test/CodeGen/RISCV/riscv32-vararg.c b/clang/test/CodeGen/RISCV/riscv32-vararg.c index 1c4e41f2f54c..00e04eb89467 100644 --- a/clang/test/CodeGen/RISCV/riscv32-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv32-vararg.c @@ -80,13 +80,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -111,7 +111,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32F-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -119,7 +119,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-ILP32F-NEXT: store double [[TMP1]], ptr [[V]], align 8 -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32F-NEXT: ret double [[TMP2]] // @@ -130,7 +130,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32D-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -138,7 +138,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-ILP32D-NEXT: store double [[TMP1]], ptr [[V]], align 8 -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32D-NEXT: ret double [[TMP2]] // @@ -149,13 +149,13 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32E-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP0:%.*]] = load double, ptr [[ARGP_CUR]], align 4 // CHECK-ILP32E-NEXT: store double [[TMP0]], ptr [[V]], align 8 -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP1:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32E-NEXT: ret double [[TMP1]] // @@ -180,7 +180,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32F-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -200,7 +200,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8 // CHECK-ILP32F-NEXT: store double [[TMP4]], ptr [[X]], align 8 -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32F-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32F-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]] @@ -215,7 +215,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32D-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -235,7 +235,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8 // CHECK-ILP32D-NEXT: store double [[TMP4]], ptr [[X]], align 8 -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32D-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32D-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]] @@ -250,7 +250,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32E-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -266,7 +266,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP2:%.*]] = load double, ptr [[ARGP_CUR3]], align 4 // CHECK-ILP32E-NEXT: store double [[TMP2]], ptr [[X]], align 8 -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32E-NEXT: [[ADD:%.*]] = fadd double [[TMP3]], [[TMP4]] @@ -296,7 +296,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32F-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -321,7 +321,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32F-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32F-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 @@ -384,7 +384,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32D-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -409,7 +409,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32D-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32D-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 @@ -472,7 +472,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32E-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -497,7 +497,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32E-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32E-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32E-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 diff --git a/clang/test/CodeGen/RISCV/riscv64-vararg.c b/clang/test/CodeGen/RISCV/riscv64-vararg.c index 634cde61320c..efdffa2687e6 100644 --- a/clang/test/CodeGen/RISCV/riscv64-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv64-vararg.c @@ -135,13 +135,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -166,7 +166,7 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca fp128, align 16 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16) @@ -174,7 +174,7 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED]], align 16 // CHECK-NEXT: store fp128 [[TMP1]], ptr [[V]], align 16 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP2:%.*]] = load fp128, ptr [[V]], align 16 // CHECK-NEXT: ret fp128 [[TMP2]] // @@ -199,7 +199,7 @@ long double f_va_2(char *fmt, ...) { // CHECK-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[X:%.*]] = alloca fp128, align 16 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16) @@ -219,7 +219,7 @@ long double f_va_2(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = load fp128, ptr [[ARGP_CUR3_ALIGNED]], align 16 // CHECK-NEXT: store fp128 [[TMP4]], ptr [[X]], align 16 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP5:%.*]] = load fp128, ptr [[V]], align 16 // CHECK-NEXT: [[TMP6:%.*]] = load fp128, ptr [[X]], align 16 // CHECK-NEXT: [[ADD:%.*]] = fadd fp128 [[TMP5]], [[TMP6]] @@ -248,7 +248,7 @@ long double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 8 // CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 @@ -267,7 +267,7 @@ long double f_va_3(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT6]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR5]], align 8 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[LS]], ptr align 8 [[TMP1]], i64 32, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 0 // CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[A]], align 2 // CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP2]] to i64 diff --git a/clang/test/CodeGen/WebAssembly/wasm-varargs.c b/clang/test/CodeGen/WebAssembly/wasm-varargs.c index c475de19ae44..e794857304e1 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-varargs.c +++ b/clang/test/CodeGen/WebAssembly/wasm-varargs.c @@ -10,13 +10,13 @@ // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -38,7 +38,7 @@ int test_i32(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i64, align 8 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -46,7 +46,7 @@ int test_i32(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-NEXT: store i64 [[TMP1]], ptr [[V]], align 8 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[V]], align 8 // CHECK-NEXT: ret i64 [[TMP2]] // @@ -73,13 +73,13 @@ struct S { // CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: ret void // struct S test_struct(char *fmt, ...) { @@ -102,7 +102,7 @@ struct Z {}; // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[U:%.*]] = alloca [[STRUCT_Z:%.*]], align 1 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 0 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -112,7 +112,7 @@ struct Z {}; // CHECK-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR1]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: ret void // struct S test_empty_struct(char *fmt, ...) { diff --git a/clang/test/CodeGen/X86/va-arg-sse.c b/clang/test/CodeGen/X86/va-arg-sse.c index e040b0e5790b..b7d00dad1453 100644 --- a/clang/test/CodeGen/X86/va-arg-sse.c +++ b/clang/test/CodeGen/X86/va-arg-sse.c @@ -21,7 +21,7 @@ struct S a[5]; // CHECK-NEXT: store i32 0, ptr [[J]], align 4 // CHECK-NEXT: store i32 0, ptr [[K]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: store ptr getelementptr inbounds ([5 x %struct.S], ptr @a, i64 0, i64 2), ptr [[P]], align 8 // CHECK-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 // CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY2]], i32 0, i32 1 @@ -52,7 +52,7 @@ struct S a[5]; // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARG]], ptr align 4 [[VAARG_ADDR]], i64 12, i1 false) // CHECK-NEXT: [[ARRAYDECAY3:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_end(ptr [[ARRAYDECAY3]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[ARRAYDECAY3]]) // CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[P]], align 8 // CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP15]], null // CHECK-NEXT: br i1 [[TOBOOL]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]] diff --git a/clang/test/CodeGen/X86/x86_64-vaarg.c b/clang/test/CodeGen/X86/x86_64-vaarg.c index a18ba8364238..07c6df14a0b8 100644 --- a/clang/test/CodeGen/X86/x86_64-vaarg.c +++ b/clang/test/CodeGen/X86/x86_64-vaarg.c @@ -13,7 +13,7 @@ typedef struct { struct {} a; } empty; // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1 // CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 0, i1 false) // CHECK-NEXT: ret void @@ -37,7 +37,7 @@ typedef struct { // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 // CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 // CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 diff --git a/clang/test/CodeGen/aarch64-ABI-align-packed.c b/clang/test/CodeGen/aarch64-ABI-align-packed.c index 2b029f645895..13c68fe54b84 100644 --- a/clang/test/CodeGen/aarch64-ABI-align-packed.c +++ b/clang/test/CodeGen/aarch64-ABI-align-packed.c @@ -73,7 +73,7 @@ __attribute__((noinline)) void named_arg_non_packed_struct(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6:[0-9]+]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_non_packed_struct(double d0, double d1, double d2, double d3, @@ -128,7 +128,7 @@ __attribute__((noinline)) void named_arg_packed_struct(double d0, double d1, dou // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_packed_struct(double d0, double d1, double d2, double d3, @@ -183,7 +183,7 @@ __attribute__((noinline)) void named_arg_packed_member(double d0, double d1, dou // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_packed_member(double d0, double d1, double d2, double d3, @@ -238,7 +238,7 @@ __attribute__((noinline)) void named_arg_aligned_struct_8(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_aligned_struct_8(double d0, double d1, double d2, double d3, @@ -293,7 +293,7 @@ __attribute__((noinline)) void named_arg_aligned_member_8(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_aligned_member_8(double d0, double d1, double d2, double d3, @@ -348,7 +348,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_8(double d0, doubl // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_pragma_packed_struct_8(double d0, double d1, double d2, double d3, @@ -403,7 +403,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_4(double d0, doubl // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_pragma_packed_struct_4(double d0, double d1, double d2, double d3, diff --git a/clang/test/CodeGen/aarch64-varargs.c b/clang/test/CodeGen/aarch64-varargs.c index 44b87029e7b3..ee4e88eda4ef 100644 --- a/clang/test/CodeGen/aarch64-varargs.c +++ b/clang/test/CodeGen/aarch64-varargs.c @@ -837,7 +837,7 @@ void check_start(int n, ...) { va_list the_list; va_start(the_list, n); // CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list -// CHECK: call void @llvm.va_start(ptr [[THE_LIST]]) +// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]]) } typedef struct {} empty; diff --git a/clang/test/CodeGen/arm-varargs.c b/clang/test/CodeGen/arm-varargs.c index f754c7f52e59..ab4ac46924e6 100644 --- a/clang/test/CodeGen/arm-varargs.c +++ b/clang/test/CodeGen/arm-varargs.c @@ -264,5 +264,5 @@ void check_start(int n, ...) { va_list the_list; va_start(the_list, n); // CHECK: [[THE_LIST:%[a-z0-9._]+]] = alloca %struct.__va_list -// CHECK: call void @llvm.va_start(ptr [[THE_LIST]]) +// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]]) } diff --git a/clang/test/CodeGen/hexagon-linux-vararg.c b/clang/test/CodeGen/hexagon-linux-vararg.c index 033e72ab449d..84945e872d28 100644 --- a/clang/test/CodeGen/hexagon-linux-vararg.c +++ b/clang/test/CodeGen/hexagon-linux-vararg.c @@ -9,7 +9,7 @@ struct AAA { int d; }; -// CHECK: call void @llvm.va_start(ptr %arraydecay) +// CHECK: call void @llvm.va_start.p0(ptr %arraydecay) // CHECK: %arraydecay1 = getelementptr inbounds [1 x %struct.__va_list_tag], // ptr %ap, i32 0, i32 0 // CHECK: br label %vaarg.maybe_reg diff --git a/clang/test/CodeGen/mips-varargs.c b/clang/test/CodeGen/mips-varargs.c index 052aedd1cd1e..029f000c121a 100644 --- a/clang/test/CodeGen/mips-varargs.c +++ b/clang/test/CodeGen/mips-varargs.c @@ -29,7 +29,7 @@ int test_i32(char *fmt, ...) { // ALL: [[V:%.*]] = alloca i32, align 4 // NEW: [[PROMOTION_TEMP:%.*]] = alloca i32, align 4 // -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // O32: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32]] [[$CHUNKSIZE:4]] // NEW: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32|i64]] [[$CHUNKSIZE:8]] @@ -45,7 +45,7 @@ int test_i32(char *fmt, ...) { // NEW: [[ARG:%.+]] = load i32, ptr [[PROMOTION_TEMP]], align 4 // ALL: store i32 [[ARG]], ptr [[V]], align 4 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } long long test_i64(char *fmt, ...) { @@ -61,7 +61,7 @@ long long test_i64(char *fmt, ...) { // ALL-LABEL: define{{.*}} i64 @test_i64(ptr{{.*}} %fmt, ...) // // ALL: %va = alloca ptr, align [[$PTRALIGN]] -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // // i64 is 8-byte aligned, while this is within O32's stack alignment there's no @@ -74,7 +74,7 @@ long long test_i64(char *fmt, ...) { // // ALL: [[ARG:%.+]] = load i64, ptr [[AP_CUR]], align 8 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } char *test_ptr(char *fmt, ...) { @@ -92,7 +92,7 @@ char *test_ptr(char *fmt, ...) { // ALL: %va = alloca ptr, align [[$PTRALIGN]] // ALL: [[V:%.*]] = alloca ptr, align [[$PTRALIGN]] // N32: [[AP_CAST:%.+]] = alloca ptr, align 4 -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // ALL: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T]] [[$CHUNKSIZE]] // ALL: store ptr [[AP_NEXT]], ptr %va, align [[$PTRALIGN]] @@ -109,7 +109,7 @@ char *test_ptr(char *fmt, ...) { // N64: [[ARG:%.+]] = load ptr, ptr [[AP_CUR]], align [[$PTRALIGN]] // ALL: store ptr [[ARG]], ptr [[V]], align [[$PTRALIGN]] // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } int test_v4i32(char *fmt, ...) { @@ -128,7 +128,7 @@ int test_v4i32(char *fmt, ...) { // // ALL: %va = alloca ptr, align [[$PTRALIGN]] // ALL: [[V:%.+]] = alloca <4 x i32>, align 16 -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // // Vectors are 16-byte aligned, however the O32 ABI has a maximum alignment of @@ -152,7 +152,7 @@ int test_v4i32(char *fmt, ...) { // N32: [[ARG:%.+]] = load <4 x i32>, ptr [[AP_CUR]], align 16 // ALL: store <4 x i32> [[ARG]], ptr [[V]], align 16 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: [[VECEXT:%.+]] = extractelement <4 x i32> {{.*}}, i32 0 // ALL: ret i32 [[VECEXT]] // ALL: } diff --git a/clang/test/CodeGen/pr53127.cpp b/clang/test/CodeGen/pr53127.cpp index 97fe1291352d..5a52b4860eec 100644 --- a/clang/test/CodeGen/pr53127.cpp +++ b/clang/test/CodeGen/pr53127.cpp @@ -34,7 +34,7 @@ void operator delete(void*); // CHECK-NEXT: br i1 [[CALL6]], label [[COND_TRUE7:%.*]], label [[COND_FALSE8:%.*]] // CHECK: cond.true7: // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: br label [[COND_END9:%.*]] // CHECK: cond.false8: // CHECK-NEXT: br label [[COND_END9]] @@ -44,7 +44,7 @@ void operator delete(void*); // CHECK: cond.true11: // CHECK-NEXT: [[ARRAYDECAY12:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0 // CHECK-NEXT: [[ARRAYDECAY13:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L2]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_copy(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]]) +// CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]]) // CHECK-NEXT: br label [[COND_END15:%.*]] // CHECK: cond.false14: // CHECK-NEXT: br label [[COND_END15]] diff --git a/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c b/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c new file mode 100644 index 000000000000..b087da34c3df --- /dev/null +++ b/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c @@ -0,0 +1,46 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple spirv64-unknown-unknown -fcuda-is-device -emit-llvm -o - %s | FileCheck %s + +struct x { + double b; + long a; +}; + +// CHECK-LABEL: define spir_func void @testva( +// CHECK-SAME: i32 noundef [[N:%.*]], ...) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AP:%.*]] = alloca ptr addrspace(4), align 8 +// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_X:%.*]], align 8 +// CHECK-NEXT: [[AP2:%.*]] = alloca ptr addrspace(4), align 8 +// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[VARET:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr [[N_ADDR]] to ptr addrspace(4) +// CHECK-NEXT: [[AP_ASCAST:%.*]] = addrspacecast ptr [[AP]] to ptr addrspace(4) +// CHECK-NEXT: [[T_ASCAST:%.*]] = addrspacecast ptr [[T]] to ptr addrspace(4) +// CHECK-NEXT: [[AP2_ASCAST:%.*]] = addrspacecast ptr [[AP2]] to ptr addrspace(4) +// CHECK-NEXT: [[V_ASCAST:%.*]] = addrspacecast ptr [[V]] to ptr addrspace(4) +// CHECK-NEXT: [[VARET_ASCAST:%.*]] = addrspacecast ptr [[VARET]] to ptr addrspace(4) +// CHECK-NEXT: store i32 [[N]], ptr addrspace(4) [[N_ADDR_ASCAST]], align 4 +// CHECK-NEXT: call void @llvm.va_start.p4(ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr addrspace(4) [[AP_ASCAST]], ptr +// CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 8 [[T_ASCAST]], ptr align 8 [[TMP0]], i64 16, i1 false) +// CHECK-NEXT: call void @llvm.va_copy.p4(ptr addrspace(4) [[AP2_ASCAST]], ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: [[TMP1:%.*]] = va_arg ptr addrspace(4) [[AP2_ASCAST]], i32 +// CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(4) [[VARET_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[VARET_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr addrspace(4) [[V_ASCAST]], align 4 +// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP2_ASCAST]]) +// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: ret void + +void testva(int n, ...) { + __builtin_va_list ap; + __builtin_va_start(ap, n); + struct x t = __builtin_va_arg(ap, struct x); + __builtin_va_list ap2; + __builtin_va_copy(ap2, ap); + int v = __builtin_va_arg(ap2, int); + __builtin_va_end(ap2); + __builtin_va_end(ap); +} diff --git a/clang/test/CodeGen/xcore-abi.c b/clang/test/CodeGen/xcore-abi.c index 4dd0f221533b..bb8d2fec46bd 100644 --- a/clang/test/CodeGen/xcore-abi.c +++ b/clang/test/CodeGen/xcore-abi.c @@ -28,7 +28,7 @@ void testva (int n, ...) { // CHECK: [[AP:%[a-z0-9]+]] = alloca ptr, align 4 // CHECK: [[V5:%[a-z0-9]+]] = alloca %struct.x, align 4 // CHECK: [[TMP:%[a-z0-9]+]] = alloca [4 x i32], align 4 - // CHECK: call void @llvm.va_start(ptr [[AP]]) + // CHECK: call void @llvm.va_start.p0(ptr [[AP]]) char* v1 = va_arg (ap, char*); f(v1); diff --git a/clang/test/CodeGenCXX/ext-int.cpp b/clang/test/CodeGenCXX/ext-int.cpp index 5a4270aef285..a1d17c840ee4 100644 --- a/clang/test/CodeGenCXX/ext-int.cpp +++ b/clang/test/CodeGenCXX/ext-int.cpp @@ -159,9 +159,9 @@ void TakesVarargs(int i, ...) { // WIN: %[[ARGS:.+]] = alloca ptr __builtin_va_start(args, i); // LIN64: %[[STARTAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] - // LIN64: call void @llvm.va_start(ptr %[[STARTAD]]) - // LIN32: call void @llvm.va_start(ptr %[[ARGS]]) - // WIN: call void @llvm.va_start(ptr %[[ARGS]]) + // LIN64: call void @llvm.va_start.p0(ptr %[[STARTAD]]) + // LIN32: call void @llvm.va_start.p0(ptr %[[ARGS]]) + // WIN: call void @llvm.va_start.p0(ptr %[[ARGS]]) _BitInt(92) A = __builtin_va_arg(args, _BitInt(92)); // LIN64: %[[AD1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] @@ -302,9 +302,9 @@ void TakesVarargs(int i, ...) { __builtin_va_end(args); // LIN64: %[[ENDAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] - // LIN64: call void @llvm.va_end(ptr %[[ENDAD]]) - // LIN32: call void @llvm.va_end(ptr %[[ARGS]]) - // WIN: call void @llvm.va_end(ptr %[[ARGS]]) + // LIN64: call void @llvm.va_end.p0(ptr %[[ENDAD]]) + // LIN32: call void @llvm.va_end.p0(ptr %[[ARGS]]) + // WIN: call void @llvm.va_end.p0(ptr %[[ARGS]]) } void typeid_tests() { // LIN: define{{.*}} void @_Z12typeid_testsv() diff --git a/clang/test/CodeGenCXX/ibm128-declarations.cpp b/clang/test/CodeGenCXX/ibm128-declarations.cpp index 5ee4f354d379..e0187e20cde4 100644 --- a/clang/test/CodeGenCXX/ibm128-declarations.cpp +++ b/clang/test/CodeGenCXX/ibm128-declarations.cpp @@ -107,13 +107,13 @@ int main(void) { // CHECK: define dso_local noundef ppc_fp128 @_Z10func_vaargiz(i32 noundef signext %n, ...) // CHECK: entry: // CHECK: store i32 %n, ptr %n.addr, align 4 -// CHECK: call void @llvm.va_start(ptr %ap) +// CHECK: call void @llvm.va_start.p0(ptr %ap) // CHECK: %argp.cur = load ptr, ptr %ap, align 8 // CHECK: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 16 // CHECK: store ptr %argp.next, ptr %ap, align 8 // CHECK: %0 = load ppc_fp128, ptr %argp.cur, align 8 // CHECK: store ppc_fp128 %0, ptr %r, align 16 -// CHECK: call void @llvm.va_end(ptr %ap) +// CHECK: call void @llvm.va_end.p0(ptr %ap) // CHECK: %1 = load ppc_fp128, ptr %r, align 16 // CHECK: ret ppc_fp128 %1 // CHECK: } diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index d221c1881d36..985a0cc41a14 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -11,7 +11,7 @@ typedef struct { struct {} a; } empty; // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1 // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 1, i1 false) // CHECK-NEXT: ret void @@ -34,7 +34,7 @@ typedef struct { // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 // CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 diff --git a/clang/test/Modules/codegen.test b/clang/test/Modules/codegen.test index 77602056defd..0af630a75480 100644 --- a/clang/test/Modules/codegen.test +++ b/clang/test/Modules/codegen.test @@ -26,7 +26,7 @@ USE: $_Z4instIiEvv = comdat any USE: $_Z10always_inlv = comdat any FOO: $_ZN13implicit_dtorD2Ev = comdat any FOO: define weak_odr void @_Z2f1PKcz(ptr noundef %fmt, ...) #{{[0-9]+}} comdat -FOO: call void @llvm.va_start(ptr %{{[a-zA-Z0-9]*}}) +FOO: call void @llvm.va_start.p0(ptr %{{[a-zA-Z0-9]*}}) Test that implicit special members are emitted into the FOO module if they're ODR used there, otherwise emit them linkonce_odr as usual in the use. diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 030b76935c7b..a4be31576931 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -12815,10 +12815,11 @@ Variable argument support is defined in LLVM with the functions. These functions are related to the similarly named macros defined in the ```` header file. -All of these functions operate on arguments that use a target-specific +All of these functions take as arguments pointers to a target-specific value type "``va_list``". The LLVM assembly language reference manual does not define what this type is, so all transformations should be -prepared to handle these functions regardless of the type used. +prepared to handle these functions regardless of the type used. The intrinsics +are overloaded, and can be used for pointers to different address spaces. This example shows how the :ref:`va_arg ` instruction and the variable argument handling intrinsic functions are used. @@ -12835,24 +12836,24 @@ variable argument handling intrinsic functions are used. define i32 @test(i32 %X, ...) { ; Initialize variable argument processing %ap = alloca %struct.va_list - call void @llvm.va_start(ptr %ap) + call void @llvm.va_start.p0(ptr %ap) ; Read a single integer argument %tmp = va_arg ptr %ap, i32 ; Demonstrate usage of llvm.va_copy and llvm.va_end %aq = alloca ptr - call void @llvm.va_copy(ptr %aq, ptr %ap) - call void @llvm.va_end(ptr %aq) + call void @llvm.va_copy.p0(ptr %aq, ptr %ap) + call void @llvm.va_end.p0(ptr %aq) ; Stop processing of arguments. - call void @llvm.va_end(ptr %ap) + call void @llvm.va_end.p0(ptr %ap) ret i32 %tmp } - declare void @llvm.va_start(ptr) - declare void @llvm.va_copy(ptr, ptr) - declare void @llvm.va_end(ptr) + declare void @llvm.va_start.p0(ptr) + declare void @llvm.va_copy.p0(ptr, ptr) + declare void @llvm.va_end.p0(ptr) .. _int_va_start: @@ -12864,7 +12865,8 @@ Syntax: :: - declare void @llvm.va_start(ptr ) + declare void @llvm.va_start.p0(ptr ) + declare void @llvm.va_start.p5(ptr addrspace(5) ) Overview: """"""""" @@ -12896,7 +12898,8 @@ Syntax: :: - declare void @llvm.va_end(ptr ) + declare void @llvm.va_end.p0(ptr ) + declare void @llvm.va_end.p5(ptr addrspace(5) ) Overview: """"""""" @@ -12929,7 +12932,8 @@ Syntax: :: - declare void @llvm.va_copy(ptr , ptr ) + declare void @llvm.va_copy.p0(ptr , ptr ) + declare void @llvm.va_copy.p5(ptr addrspace(5) , ptr addrspace(5) ) Overview: """"""""" @@ -12942,6 +12946,7 @@ Arguments: The first argument is a pointer to a ``va_list`` element to initialize. The second argument is a pointer to a ``va_list`` element to copy from. +The address spaces of the two arguments must match. Semantics: """""""""" diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index d0ef9c25f39e..764902426f0b 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -700,10 +700,13 @@ class MSBuiltin { //===--------------- Variable Argument Handling Intrinsics ----------------===// // -def int_vastart : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], [], "llvm.va_start">; -def int_vacopy : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], - "llvm.va_copy">; -def int_vaend : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], [], "llvm.va_end">; +def int_vastart : DefaultAttrsIntrinsic<[], + [llvm_anyptr_ty], [], "llvm.va_start">; +def int_vacopy : DefaultAttrsIntrinsic<[], + [llvm_anyptr_ty, LLVMMatchType<0>], [], + "llvm.va_copy">; +def int_vaend : DefaultAttrsIntrinsic<[], + [llvm_anyptr_ty], [], "llvm.va_end">; //===------------------- Garbage Collection Intrinsics --------------------===// // diff --git a/llvm/test/Bitcode/compatibility-3.6.ll b/llvm/test/Bitcode/compatibility-3.6.ll index b1f4abf7b8c5..2190e2fbccf2 100644 --- a/llvm/test/Bitcode/compatibility-3.6.ll +++ b/llvm/test/Bitcode/compatibility-3.6.ll @@ -1061,16 +1061,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1178,11 +1178,11 @@ define void @intrinsics.codegen() { ; CHECK: attributes #27 = { uwtable } ; CHECK: attributes #28 = { "cpu"="cortex-a8" } ; CHECK: attributes #29 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #30 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #31 = { nounwind memory(argmem: read) } -; CHECK: attributes #32 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #33 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #34 = { nocallback nounwind } +; CHECK: attributes #30 = { nounwind memory(argmem: read) } +; CHECK: attributes #31 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #32 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #33 = { nocallback nounwind } +; CHECK: attributes #34 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #36 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-3.7.ll b/llvm/test/Bitcode/compatibility-3.7.ll index 91e55f6eda59..7e59b5c1be6e 100644 --- a/llvm/test/Bitcode/compatibility-3.7.ll +++ b/llvm/test/Bitcode/compatibility-3.7.ll @@ -1092,16 +1092,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1241,11 +1241,11 @@ define void @misc.metadata() { ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #33 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #34 = { nounwind memory(argmem: read) } -; CHECK: attributes #35 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #37 = { nocallback nounwind } +; CHECK: attributes #33 = { nounwind memory(argmem: read) } +; CHECK: attributes #34 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #36 = { nocallback nounwind } +; CHECK: attributes #37 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #39 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-3.8.ll b/llvm/test/Bitcode/compatibility-3.8.ll index aa4d8b14968c..ebd1f2fff8c9 100644 --- a/llvm/test/Bitcode/compatibility-3.8.ll +++ b/llvm/test/Bitcode/compatibility-3.8.ll @@ -1247,16 +1247,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1551,11 +1551,11 @@ normal: ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #42 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-3.9.ll b/llvm/test/Bitcode/compatibility-3.9.ll index e3c84f6e6007..c34f04ceb0de 100644 --- a/llvm/test/Bitcode/compatibility-3.9.ll +++ b/llvm/test/Bitcode/compatibility-3.9.ll @@ -1318,16 +1318,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1624,11 +1624,11 @@ declare void @f.writeonly() writeonly ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #43 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-4.0.ll b/llvm/test/Bitcode/compatibility-4.0.ll index 06cb842059a4..05bffda1d117 100644 --- a/llvm/test/Bitcode/compatibility-4.0.ll +++ b/llvm/test/Bitcode/compatibility-4.0.ll @@ -1318,16 +1318,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1649,11 +1649,11 @@ define i8** @constexpr() { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #43 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-5.0.ll b/llvm/test/Bitcode/compatibility-5.0.ll index f9ae558917cd..0c872289c62b 100644 --- a/llvm/test/Bitcode/compatibility-5.0.ll +++ b/llvm/test/Bitcode/compatibility-5.0.ll @@ -1330,16 +1330,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1664,11 +1664,11 @@ define i8** @constexpr() { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #43 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } diff --git a/llvm/test/Bitcode/compatibility-6.0.ll b/llvm/test/Bitcode/compatibility-6.0.ll index 1458e1b639ad..44c680885be3 100644 --- a/llvm/test/Bitcode/compatibility-6.0.ll +++ b/llvm/test/Bitcode/compatibility-6.0.ll @@ -1340,16 +1340,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1674,11 +1674,11 @@ define i8** @constexpr() { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #43 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll index fa8b0520567a..b374924516d6 100644 --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -1648,16 +1648,16 @@ define void @instructions.va_arg(ptr %v, ...) { %ap = alloca ptr call void @llvm.va_start(ptr %ap) - ; CHECK: call void @llvm.va_start(ptr %ap) + ; CHECK: call void @llvm.va_start.p0(ptr %ap) va_arg ptr %ap, i32 ; CHECK: va_arg ptr %ap, i32 call void @llvm.va_copy(ptr %v, ptr %ap) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap) call void @llvm.va_end(ptr %ap) - ; CHECK: call void @llvm.va_end(ptr %ap) + ; CHECK: call void @llvm.va_end.p0(ptr %ap) ret void } @@ -2091,12 +2091,12 @@ define float @nofpclass_callsites(float %arg) { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } -; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #42 = { memory(write) } ; CHECK: attributes #43 = { speculatable } ; CHECK: attributes #44 = { strictfp } diff --git a/llvm/test/Bitcode/thinlto-function-summary.ll b/llvm/test/Bitcode/thinlto-function-summary.ll index 799759ebcac1..13c6611843d6 100644 --- a/llvm/test/Bitcode/thinlto-function-summary.ll +++ b/llvm/test/Bitcode/thinlto-function-summary.ll @@ -13,9 +13,9 @@ ; "variadic" ; BC-NEXT: { // Variadic function intrinsics. // -def LLVM_VaStartOp : LLVM_ZeroResultIntrOp<"vastart">, +def LLVM_VaStartOp : LLVM_ZeroResultIntrOp<"vastart", [0]>, Arguments<(ins LLVM_AnyPointer:$arg_list)> { let assemblyFormat = "$arg_list attr-dict `:` qualified(type($arg_list))"; let summary = "Initializes `arg_list` for subsequent variadic argument extractions."; } -def LLVM_VaCopyOp : LLVM_ZeroResultIntrOp<"vacopy">, +def LLVM_VaCopyOp : LLVM_ZeroResultIntrOp<"vacopy", [0]>, Arguments<(ins LLVM_AnyPointer:$dest_list, LLVM_AnyPointer:$src_list)> { let assemblyFormat = "$src_list `to` $dest_list attr-dict `:` type(operands)"; let summary = "Copies the current argument position from `src_list` to `dest_list`."; } -def LLVM_VaEndOp : LLVM_ZeroResultIntrOp<"vaend">, +def LLVM_VaEndOp : LLVM_ZeroResultIntrOp<"vaend", [0]>, Arguments<(ins LLVM_AnyPointer:$arg_list)> { let assemblyFormat = "$arg_list attr-dict `:` qualified(type($arg_list))"; let summary = "Destroys `arg_list`, which has been initialized by `intr.vastart` or `intr.vacopy`."; diff --git a/mlir/test/Target/LLVMIR/Import/basic.ll b/mlir/test/Target/LLVMIR/Import/basic.ll index a059425d9780..448b0ebe2574 100644 --- a/mlir/test/Target/LLVMIR/Import/basic.ll +++ b/mlir/test/Target/LLVMIR/Import/basic.ll @@ -72,26 +72,26 @@ define i32 @useFreezeOp(i32 %x) { ; Varadic function definition %struct.va_list = type { ptr } -declare void @llvm.va_start(ptr) -declare void @llvm.va_copy(ptr, ptr) -declare void @llvm.va_end(ptr) +declare void @llvm.va_start.p0(ptr) +declare void @llvm.va_copy.p0(ptr, ptr) +declare void @llvm.va_end.p0(ptr) ; CHECK-LABEL: llvm.func @variadic_function define void @variadic_function(i32 %X, ...) { ; CHECK: %[[ALLOCA0:.+]] = llvm.alloca %{{.*}} x !llvm.struct<"struct.va_list", (ptr)> {{.*}} : (i32) -> !llvm.ptr %ap = alloca %struct.va_list ; CHECK: llvm.intr.vastart %[[ALLOCA0]] - call void @llvm.va_start(ptr %ap) + call void @llvm.va_start.p0(ptr %ap) ; CHECK: %[[ALLOCA1:.+]] = llvm.alloca %{{.*}} x !llvm.ptr {{.*}} : (i32) -> !llvm.ptr %aq = alloca ptr ; CHECK: llvm.intr.vacopy %[[ALLOCA0]] to %[[ALLOCA1]] - call void @llvm.va_copy(ptr %aq, ptr %ap) + call void @llvm.va_copy.p0(ptr %aq, ptr %ap) ; CHECK: llvm.intr.vaend %[[ALLOCA1]] - call void @llvm.va_end(ptr %aq) + call void @llvm.va_end.p0(ptr %aq) ; CHECK: llvm.intr.vaend %[[ALLOCA0]] - call void @llvm.va_end(ptr %ap) + call void @llvm.va_end.p0(ptr %ap) ; CHECK: llvm.return ret void } diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic.ll b/mlir/test/Target/LLVMIR/Import/intrinsic.ll index 85561839f31a..0cefb4f8983a 100644 --- a/mlir/test/Target/LLVMIR/Import/intrinsic.ll +++ b/mlir/test/Target/LLVMIR/Import/intrinsic.ll @@ -599,11 +599,11 @@ define void @ushl_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) { ; CHECK-LABEL: llvm.func @va_intrinsics_test define void @va_intrinsics_test(ptr %0, ptr %1) { ; CHECK: llvm.intr.vastart %{{.*}} - call void @llvm.va_start(ptr %0) + call void @llvm.va_start.p0(ptr %0) ; CHECK: llvm.intr.vacopy %{{.*}} to %{{.*}} - call void @llvm.va_copy(ptr %1, ptr %0) + call void @llvm.va_copy.p0(ptr %1, ptr %0) ; CHECK: llvm.intr.vaend %{{.*}} - call void @llvm.va_end(ptr %0) + call void @llvm.va_end.p0(ptr %0) ret void } @@ -1076,9 +1076,9 @@ declare ptr @llvm.stacksave.p0() declare ptr addrspace(1) @llvm.stacksave.p1() declare void @llvm.stackrestore.p0(ptr) declare void @llvm.stackrestore.p1(ptr addrspace(1)) -declare void @llvm.va_start(ptr) -declare void @llvm.va_copy(ptr, ptr) -declare void @llvm.va_end(ptr) +declare void @llvm.va_start.p0(ptr) +declare void @llvm.va_copy.p0(ptr, ptr) +declare void @llvm.va_end.p0(ptr) declare <8 x i32> @llvm.vp.add.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.sub.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.mul.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index c38c7ea587d2..97f37939551d 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2251,14 +2251,14 @@ llvm.func @vararg_function(%arg0: i32, ...) { %1 = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[ALLOCA0:.+]] = alloca %struct.va_list, align 8 %2 = llvm.alloca %1 x !llvm.struct<"struct.va_list", (ptr)> {alignment = 8 : i64} : (i32) -> !llvm.ptr - // CHECK: call void @llvm.va_start(ptr %[[ALLOCA0]]) + // CHECK: call void @llvm.va_start.p0(ptr %[[ALLOCA0]]) llvm.intr.vastart %2 : !llvm.ptr // CHECK: %[[ALLOCA1:.+]] = alloca ptr, align 8 %4 = llvm.alloca %0 x !llvm.ptr {alignment = 8 : i64} : (i32) -> !llvm.ptr - // CHECK: call void @llvm.va_copy(ptr %[[ALLOCA1]], ptr %[[ALLOCA0]]) + // CHECK: call void @llvm.va_copy.p0(ptr %[[ALLOCA1]], ptr %[[ALLOCA0]]) llvm.intr.vacopy %2 to %4 : !llvm.ptr, !llvm.ptr - // CHECK: call void @llvm.va_end(ptr %[[ALLOCA1]]) - // CHECK: call void @llvm.va_end(ptr %[[ALLOCA0]]) + // CHECK: call void @llvm.va_end.p0(ptr %[[ALLOCA1]]) + // CHECK: call void @llvm.va_end.p0(ptr %[[ALLOCA0]]) llvm.intr.vaend %4 : !llvm.ptr llvm.intr.vaend %2 : !llvm.ptr // CHECK: ret void -- GitLab From ef316da4a2c5954a02c92707b5cb621402b76910 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 27 Mar 2024 00:56:47 +0530 Subject: [PATCH 047/541] AMDGPU: Fix dead check prefixes in test --- .../AMDGPU/global_atomics_i32_system.ll | 564 ------------------ .../AMDGPU/global_atomics_i64_system.ll | 564 ------------------ 2 files changed, 1128 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll index 76ec1cc84f55..99d02ffaa523 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll @@ -358,65 +358,6 @@ define amdgpu_gfx i32 @global_atomic_xchg_i32_ret_offset_scalar(ptr addrspace(1) ; --------------------------------------------------------------------- define void @global_atomic_xchg_f32_noret(ptr addrspace(1) %ptr, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB0_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB0_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB0_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -450,69 +391,6 @@ define void @global_atomic_xchg_f32_noret(ptr addrspace(1) %ptr, float %in) { } define void @global_atomic_xchg_f32_noret_offset(ptr addrspace(1) %out, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f32_e32 v0, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB1_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v0, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB1_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB1_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -549,71 +427,6 @@ define void @global_atomic_xchg_f32_noret_offset(ptr addrspace(1) %out, float %i } define float @global_atomic_xchg_f32_ret(ptr addrspace(1) %ptr, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v4, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB2_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v0, v4 -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v4, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB2_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v0, v4 -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB2_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -648,73 +461,6 @@ define float @global_atomic_xchg_f32_ret(ptr addrspace(1) %ptr, float %in) { } define float @global_atomic_xchg_f32_ret_offset(ptr addrspace(1) %out, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f32_e32 v4, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v0, v[4:5] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v0 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB3_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v4, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v0, v[4:5] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v0 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB3_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB3_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -752,80 +498,6 @@ define float @global_atomic_xchg_f32_ret_offset(ptr addrspace(1) %out, float %in } define amdgpu_gfx void @global_atomic_xchg_f32_noret_scalar(ptr addrspace(1) inreg %ptr, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s4 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB4_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s4 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB4_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB4_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -876,84 +548,6 @@ define amdgpu_gfx void @global_atomic_xchg_f32_noret_scalar(ptr addrspace(1) inr } define amdgpu_gfx void @global_atomic_xchg_f32_noret_offset_scalar(ptr addrspace(1) inreg %out, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s34 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB5_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s34 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB5_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB5_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1007,83 +601,6 @@ define amdgpu_gfx void @global_atomic_xchg_f32_noret_offset_scalar(ptr addrspace } define amdgpu_gfx float @global_atomic_xchg_f32_ret_scalar(ptr addrspace(1) inreg %ptr, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB6_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB6_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB6_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1134,87 +651,6 @@ define amdgpu_gfx float @global_atomic_xchg_f32_ret_scalar(ptr addrspace(1) inre } define amdgpu_gfx float @global_atomic_xchg_f32_ret_offset_scalar(ptr addrspace(1) inreg %out, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB7_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB7_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB7_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll index d137f471910d..380ce7f3b939 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll @@ -372,65 +372,6 @@ define amdgpu_gfx i64 @global_atomic_xchg_i64_ret_offset_scalar(ptr addrspace(1) ; --------------------------------------------------------------------- define void @global_atomic_xchg_f64_noret(ptr addrspace(1) %ptr, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB0_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB0_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB0_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -464,69 +405,6 @@ define void @global_atomic_xchg_f64_noret(ptr addrspace(1) %ptr, double %in) { } define void @global_atomic_xchg_f64_noret_offset(ptr addrspace(1) %out, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f64_e32 v0, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB1_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v0, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB1_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB1_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -563,71 +441,6 @@ define void @global_atomic_xchg_f64_noret_offset(ptr addrspace(1) %out, double % } define double @global_atomic_xchg_f64_ret(ptr addrspace(1) %ptr, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v4, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB2_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v0, v4 -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v4, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB2_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v0, v4 -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB2_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -663,73 +476,6 @@ define double @global_atomic_xchg_f64_ret(ptr addrspace(1) %ptr, double %in) { } define double @global_atomic_xchg_f64_ret_offset(ptr addrspace(1) %out, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f64_e32 v4, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v0, v[4:5] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v0 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB3_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v4, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v0, v[4:5] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v0 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB3_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB3_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -768,80 +514,6 @@ define double @global_atomic_xchg_f64_ret_offset(ptr addrspace(1) %out, double % } define amdgpu_gfx void @global_atomic_xchg_f64_noret_scalar(ptr addrspace(1) inreg %ptr, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s4 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB4_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s4 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB4_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB4_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -896,84 +568,6 @@ define amdgpu_gfx void @global_atomic_xchg_f64_noret_scalar(ptr addrspace(1) inr } define amdgpu_gfx void @global_atomic_xchg_f64_noret_offset_scalar(ptr addrspace(1) inreg %out, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s34 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB5_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s34 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB5_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB5_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1029,83 +623,6 @@ define amdgpu_gfx void @global_atomic_xchg_f64_noret_offset_scalar(ptr addrspace } define amdgpu_gfx double @global_atomic_xchg_f64_ret_scalar(ptr addrspace(1) inreg %ptr, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB6_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB6_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB6_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1160,87 +677,6 @@ define amdgpu_gfx double @global_atomic_xchg_f64_ret_scalar(ptr addrspace(1) inr } define amdgpu_gfx double @global_atomic_xchg_f64_ret_offset_scalar(ptr addrspace(1) inreg %out, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB7_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB7_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB7_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -- GitLab From 1103a2a337e90d8c7cc417b89e43c7a33aaea21e Mon Sep 17 00:00:00 2001 From: Janek van Oirschot <5994977+JanekvO@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:59:56 +0000 Subject: [PATCH 048/541] Reland [AMDGPU] MCExpr-ify MC layer kernel descriptor (#86494) Kernel descriptor attributes, with their respective emit and asm parse functionality, converted to MCExpr. Relands #80855 with fixes --- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 40 +- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h | 11 +- .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 194 ++++++--- .../MCTargetDesc/AMDGPUMCKernelDescriptor.cpp | 98 +++++ .../MCTargetDesc/AMDGPUMCKernelDescriptor.h | 54 +++ .../MCTargetDesc/AMDGPUTargetStreamer.cpp | 404 +++++++++++------- .../MCTargetDesc/AMDGPUTargetStreamer.h | 33 +- .../Target/AMDGPU/MCTargetDesc/CMakeLists.txt | 1 + .../Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp | 41 -- llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h | 7 - llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s | 27 ++ llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s | 281 ++++++++++++ llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s | 190 ++++++++ llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s | 186 ++++++++ llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s | 184 ++++++++ llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s | 168 ++++++++ llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s | 171 ++++++++ llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s | 148 +++++++ llvm/test/MC/AMDGPU/hsa-tg-split.s | 74 ++++ 19 files changed, 1999 insertions(+), 313 deletions(-) create mode 100644 llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.cpp create mode 100644 llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.h create mode 100644 llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s create mode 100644 llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s create mode 100644 llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s create mode 100644 llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s create mode 100644 llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s create mode 100644 llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s create mode 100644 llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s create mode 100644 llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s create mode 100644 llvm/test/MC/AMDGPU/hsa-tg-split.s diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp index 72e8b59e0a40..052b231d62a3 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -22,6 +22,7 @@ #include "AMDKernelCodeT.h" #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUInstPrinter.h" +#include "MCTargetDesc/AMDGPUMCKernelDescriptor.h" #include "MCTargetDesc/AMDGPUTargetStreamer.h" #include "R600AsmPrinter.h" #include "SIMachineFunctionInfo.h" @@ -428,38 +429,43 @@ uint16_t AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties( return KernelCodeProperties; } -amdhsa::kernel_descriptor_t AMDGPUAsmPrinter::getAmdhsaKernelDescriptor( - const MachineFunction &MF, - const SIProgramInfo &PI) const { +MCKernelDescriptor +AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF, + const SIProgramInfo &PI) const { const GCNSubtarget &STM = MF.getSubtarget(); const Function &F = MF.getFunction(); const SIMachineFunctionInfo *Info = MF.getInfo(); + MCContext &Ctx = MF.getContext(); - amdhsa::kernel_descriptor_t KernelDescriptor; - memset(&KernelDescriptor, 0x0, sizeof(KernelDescriptor)); + MCKernelDescriptor KernelDescriptor; assert(isUInt<32>(PI.ScratchSize)); assert(isUInt<32>(PI.getComputePGMRSrc1(STM))); assert(isUInt<32>(PI.getComputePGMRSrc2())); - KernelDescriptor.group_segment_fixed_size = PI.LDSSize; - KernelDescriptor.private_segment_fixed_size = PI.ScratchSize; + KernelDescriptor.group_segment_fixed_size = + MCConstantExpr::create(PI.LDSSize, Ctx); + KernelDescriptor.private_segment_fixed_size = + MCConstantExpr::create(PI.ScratchSize, Ctx); Align MaxKernArgAlign; - KernelDescriptor.kernarg_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign); + KernelDescriptor.kernarg_size = MCConstantExpr::create( + STM.getKernArgSegmentSize(F, MaxKernArgAlign), Ctx); - KernelDescriptor.compute_pgm_rsrc1 = PI.getComputePGMRSrc1(STM); - KernelDescriptor.compute_pgm_rsrc2 = PI.getComputePGMRSrc2(); - KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF); + KernelDescriptor.compute_pgm_rsrc1 = + MCConstantExpr::create(PI.getComputePGMRSrc1(STM), Ctx); + KernelDescriptor.compute_pgm_rsrc2 = + MCConstantExpr::create(PI.getComputePGMRSrc2(), Ctx); + KernelDescriptor.kernel_code_properties = + MCConstantExpr::create(getAmdhsaKernelCodeProperties(MF), Ctx); assert(STM.hasGFX90AInsts() || CurrentProgramInfo.ComputePGMRSrc3GFX90A == 0); - if (STM.hasGFX90AInsts()) - KernelDescriptor.compute_pgm_rsrc3 = - CurrentProgramInfo.ComputePGMRSrc3GFX90A; + KernelDescriptor.compute_pgm_rsrc3 = MCConstantExpr::create( + STM.hasGFX90AInsts() ? CurrentProgramInfo.ComputePGMRSrc3GFX90A : 0, Ctx); - if (AMDGPU::hasKernargPreload(STM)) - KernelDescriptor.kernarg_preload = - static_cast(Info->getNumKernargPreloadedSGPRs()); + KernelDescriptor.kernarg_preload = MCConstantExpr::create( + AMDGPU::hasKernargPreload(STM) ? Info->getNumKernargPreloadedSGPRs() : 0, + Ctx); return KernelDescriptor; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h index 79326cd3d328..b8b2718d293e 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h @@ -28,15 +28,12 @@ class MCCodeEmitter; class MCOperand; namespace AMDGPU { +struct MCKernelDescriptor; namespace HSAMD { class MetadataStreamer; } } // namespace AMDGPU -namespace amdhsa { -struct kernel_descriptor_t; -} - class AMDGPUAsmPrinter final : public AsmPrinter { private: unsigned CodeObjectVersion; @@ -75,9 +72,9 @@ private: uint16_t getAmdhsaKernelCodeProperties( const MachineFunction &MF) const; - amdhsa::kernel_descriptor_t getAmdhsaKernelDescriptor( - const MachineFunction &MF, - const SIProgramInfo &PI) const; + AMDGPU::MCKernelDescriptor + getAmdhsaKernelDescriptor(const MachineFunction &MF, + const SIProgramInfo &PI) const; void initTargetStreamer(Module &M); diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 4648df199c74..294fc683fe92 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -8,6 +8,7 @@ #include "AMDKernelCodeT.h" #include "MCTargetDesc/AMDGPUMCExpr.h" +#include "MCTargetDesc/AMDGPUMCKernelDescriptor.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "MCTargetDesc/AMDGPUTargetStreamer.h" #include "SIDefines.h" @@ -5417,7 +5418,9 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { if (getParser().parseIdentifier(KernelName)) return true; - kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI()); + AMDGPU::MCKernelDescriptor KD = + AMDGPU::MCKernelDescriptor::getDefaultAmdhsaKernelDescriptor( + &getSTI(), getContext()); StringSet<> Seen; @@ -5457,89 +5460,111 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { return TokError(".amdhsa_ directives cannot be repeated"); SMLoc ValStart = getLoc(); - int64_t IVal; - if (getParser().parseAbsoluteExpression(IVal)) + const MCExpr *ExprVal; + if (getParser().parseExpression(ExprVal)) return true; SMLoc ValEnd = getLoc(); SMRange ValRange = SMRange(ValStart, ValEnd); - if (IVal < 0) - return OutOfRangeError(ValRange); - + int64_t IVal = 0; uint64_t Val = IVal; + bool EvaluatableExpr; + if ((EvaluatableExpr = ExprVal->evaluateAsAbsolute(IVal))) { + if (IVal < 0) + return OutOfRangeError(ValRange); + Val = IVal; + } #define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \ - if (!isUInt(VALUE)) \ + if (!isUInt(Val)) \ return OutOfRangeError(RANGE); \ - AMDHSA_BITS_SET(FIELD, ENTRY, VALUE); + AMDGPU::MCKernelDescriptor::bits_set(FIELD, VALUE, ENTRY##_SHIFT, ENTRY, \ + getContext()); + +// Some fields use the parsed value immediately which requires the expression to +// be solvable. +#define EXPR_RESOLVE_OR_ERROR(RESOLVED) \ + if (!(RESOLVED)) \ + return Error(IDRange.Start, "directive should have resolvable expression", \ + IDRange); if (ID == ".amdhsa_group_segment_fixed_size") { - if (!isUInt(Val)) + if (!isUInt(Val)) return OutOfRangeError(ValRange); - KD.group_segment_fixed_size = Val; + KD.group_segment_fixed_size = ExprVal; } else if (ID == ".amdhsa_private_segment_fixed_size") { - if (!isUInt(Val)) + if (!isUInt(Val)) return OutOfRangeError(ValRange); - KD.private_segment_fixed_size = Val; + KD.private_segment_fixed_size = ExprVal; } else if (ID == ".amdhsa_kernarg_size") { - if (!isUInt(Val)) + if (!isUInt(Val)) return OutOfRangeError(ValRange); - KD.kernarg_size = Val; + KD.kernarg_size = ExprVal; } else if (ID == ".amdhsa_user_sgpr_count") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); ExplicitUserSGPRCount = Val; } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (hasArchitectedFlatScratch()) return Error(IDRange.Start, "directive is not supported with architected flat scratch", IDRange); PARSE_BITS_ENTRY(KD.kernel_code_properties, KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, - Val, ValRange); + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 4; } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_length") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (!hasKernargPreload()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); if (Val > getMaxNumUserSGPRs()) return OutOfRangeError(ValRange); - PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, Val, + PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, ExprVal, ValRange); if (Val) { ImpliedUserSGPRCount += Val; PreloadLength = Val; } } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_offset") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (!hasKernargPreload()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); if (Val >= 1024) return OutOfRangeError(ValRange); - PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, Val, + PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, ExprVal, ValRange); if (Val) PreloadOffset = Val; } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val, + KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_queue_ptr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val, + KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR, - Val, ValRange); + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_dispatch_id") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val, + KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; @@ -5548,34 +5573,39 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { return Error(IDRange.Start, "directive is not supported with architected flat scratch", IDRange); + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val, - ValRange); + KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_private_segment_size") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, - Val, ValRange); + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 1; } else if (ID == ".amdhsa_wavefront_size32") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); EnableWavefrontSize32 = Val; PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, - Val, ValRange); + KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, ExprVal, + ValRange); } else if (ID == ".amdhsa_uses_dynamic_stack") { PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, Val, ValRange); + KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, ExprVal, + ValRange); } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") { if (hasArchitectedFlatScratch()) return Error(IDRange.Start, "directive is not supported with architected flat scratch", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, Val, ValRange); + COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal, + ValRange); } else if (ID == ".amdhsa_enable_private_segment") { if (!hasArchitectedFlatScratch()) return Error( @@ -5583,42 +5613,48 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { "directive is not supported without architected flat scratch", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, Val, ValRange); + COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal, + ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, ExprVal, ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, ExprVal, ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, ExprVal, ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_info") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, ExprVal, ValRange); } else if (ID == ".amdhsa_system_vgpr_workitem_id") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val, + COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, ExprVal, ValRange); } else if (ID == ".amdhsa_next_free_vgpr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); VGPRRange = ValRange; NextFreeVGPR = Val; } else if (ID == ".amdhsa_next_free_sgpr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); SGPRRange = ValRange; NextFreeSGPR = Val; } else if (ID == ".amdhsa_accum_offset") { if (!isGFX90A()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); AccumOffset = Val; } else if (ID == ".amdhsa_reserve_vcc") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (!isUInt<1>(Val)) return OutOfRangeError(ValRange); ReserveVCC = Val; } else if (ID == ".amdhsa_reserve_flat_scratch") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (IVersion.Major < 7) return Error(IDRange.Start, "directive requires gfx7+", IDRange); if (hasArchitectedFlatScratch()) @@ -5638,97 +5674,105 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { IDRange); } else if (ID == ".amdhsa_float_round_mode_32") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange); + COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, ExprVal, + ValRange); } else if (ID == ".amdhsa_float_round_mode_16_64") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange); + COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, ExprVal, + ValRange); } else if (ID == ".amdhsa_float_denorm_mode_32") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange); + COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, ExprVal, + ValRange); } else if (ID == ".amdhsa_float_denorm_mode_16_64") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val, + COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, ExprVal, ValRange); } else if (ID == ".amdhsa_dx10_clamp") { if (IVersion.Major >= 12) return Error(IDRange.Start, "directive unsupported on gfx12+", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, Val, + COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, ExprVal, ValRange); } else if (ID == ".amdhsa_ieee_mode") { if (IVersion.Major >= 12) return Error(IDRange.Start, "directive unsupported on gfx12+", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, Val, + COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, ExprVal, ValRange); } else if (ID == ".amdhsa_fp16_overflow") { if (IVersion.Major < 9) return Error(IDRange.Start, "directive requires gfx9+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, ExprVal, ValRange); } else if (ID == ".amdhsa_tg_split") { if (!isGFX90A()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Val, - ValRange); + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, + ExprVal, ValRange); } else if (ID == ".amdhsa_workgroup_processor_mode") { if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, ExprVal, ValRange); } else if (ID == ".amdhsa_memory_ordered") { if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, ExprVal, ValRange); } else if (ID == ".amdhsa_forward_progress") { if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, ExprVal, ValRange); } else if (ID == ".amdhsa_shared_vgpr_count") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (IVersion.Major < 10 || IVersion.Major >= 12) return Error(IDRange.Start, "directive requires gfx10 or gfx11", IDRange); SharedVGPRCount = Val; PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, - COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, Val, + COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") { PARSE_BITS_ENTRY( KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val, - ValRange); + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_denorm_src") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") { PARSE_BITS_ENTRY( KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val, - ValRange); + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_overflow") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_underflow") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_inexact") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_int_div_zero") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_round_robin_scheduling") { if (IVersion.Major < 12) return Error(IDRange.Start, "directive requires gfx12+", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, Val, + COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, ExprVal, ValRange); } else { return Error(IDRange.Start, "unknown .amdhsa_kernel directive", IDRange); @@ -5755,15 +5799,18 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { if (!isUInt( VGPRBlocks)) return OutOfRangeError(VGPRRange); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks); + AMDGPU::MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, MCConstantExpr::create(VGPRBlocks, getContext()), + COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_SHIFT, + COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, getContext()); if (!isUInt( SGPRBlocks)) return OutOfRangeError(SGPRRange); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, - SGPRBlocks); + AMDGPU::MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, MCConstantExpr::create(SGPRBlocks, getContext()), + COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_SHIFT, + COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, getContext()); if (ExplicitUserSGPRCount && ImpliedUserSGPRCount > *ExplicitUserSGPRCount) return TokError("amdgpu_user_sgpr_count smaller than than implied by " @@ -5774,11 +5821,17 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { if (!isUInt(UserSGPRCount)) return TokError("too many user SGPRs enabled"); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, - UserSGPRCount); - - if (PreloadLength && KD.kernarg_size && - (PreloadLength * 4 + PreloadOffset * 4 > KD.kernarg_size)) + AMDGPU::MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc2, MCConstantExpr::create(UserSGPRCount, getContext()), + COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_SHIFT, + COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, getContext()); + + int64_t IVal = 0; + if (!KD.kernarg_size->evaluateAsAbsolute(IVal)) + return TokError("Kernarg size should be resolvable"); + uint64_t kernarg_size = IVal; + if (PreloadLength && kernarg_size && + (PreloadLength * 4 + PreloadOffset * 4 > kernarg_size)) return TokError("Kernarg preload length + offset is larger than the " "kernarg segment size"); @@ -5790,8 +5843,11 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { "increments of 4"); if (AccumOffset > alignTo(std::max((uint64_t)1, NextFreeVGPR), 4)) return TokError("accum_offset exceeds total VGPR allocation"); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, - (AccumOffset / 4 - 1)); + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc3, + MCConstantExpr::create(AccumOffset / 4 - 1, getContext()), + COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, + COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, getContext()); } if (IVersion.Major >= 10 && IVersion.Major < 12) { diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.cpp new file mode 100644 index 000000000000..77e7e30ff528 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.cpp @@ -0,0 +1,98 @@ +//===--- AMDHSAKernelDescriptor.h -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "AMDGPUMCKernelDescriptor.h" +#include "AMDGPUMCTargetDesc.h" +#include "Utils/AMDGPUBaseInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/TargetParser/TargetParser.h" + +using namespace llvm; +using namespace llvm::AMDGPU; + +MCKernelDescriptor +MCKernelDescriptor::getDefaultAmdhsaKernelDescriptor(const MCSubtargetInfo *STI, + MCContext &Ctx) { + IsaVersion Version = getIsaVersion(STI->getCPU()); + + MCKernelDescriptor KD; + const MCExpr *ZeroMCExpr = MCConstantExpr::create(0, Ctx); + const MCExpr *OneMCExpr = MCConstantExpr::create(1, Ctx); + + KD.group_segment_fixed_size = ZeroMCExpr; + KD.private_segment_fixed_size = ZeroMCExpr; + KD.compute_pgm_rsrc1 = ZeroMCExpr; + KD.compute_pgm_rsrc2 = ZeroMCExpr; + KD.compute_pgm_rsrc3 = ZeroMCExpr; + KD.kernarg_size = ZeroMCExpr; + KD.kernel_code_properties = ZeroMCExpr; + KD.kernarg_preload = ZeroMCExpr; + + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, + MCConstantExpr::create(amdhsa::FLOAT_DENORM_MODE_FLUSH_NONE, Ctx), + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Ctx); + if (Version.Major < 12) { + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, Ctx); + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, Ctx); + } + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc2, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Ctx); + if (Version.Major >= 10) { + if (STI->getFeatureBits().test(FeatureWavefrontSize32)) + MCKernelDescriptor::bits_set( + KD.kernel_code_properties, OneMCExpr, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, Ctx); + if (!STI->getFeatureBits().test(FeatureCuMode)) + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, Ctx); + + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, Ctx); + } + if (AMDGPU::isGFX90A(*STI) && STI->getFeatureBits().test(FeatureTgSplit)) + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc3, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Ctx); + return KD; +} + +void MCKernelDescriptor::bits_set(const MCExpr *&Dst, const MCExpr *Value, + uint32_t Shift, uint32_t Mask, + MCContext &Ctx) { + auto Sft = MCConstantExpr::create(Shift, Ctx); + auto Msk = MCConstantExpr::create(Mask, Ctx); + Dst = MCBinaryExpr::createAnd(Dst, MCUnaryExpr::createNot(Msk, Ctx), Ctx); + Dst = MCBinaryExpr::createOr(Dst, MCBinaryExpr::createShl(Value, Sft, Ctx), + Ctx); +} + +const MCExpr *MCKernelDescriptor::bits_get(const MCExpr *Src, uint32_t Shift, + uint32_t Mask, MCContext &Ctx) { + auto Sft = MCConstantExpr::create(Shift, Ctx); + auto Msk = MCConstantExpr::create(Mask, Ctx); + return MCBinaryExpr::createLShr(MCBinaryExpr::createAnd(Src, Msk, Ctx), Sft, + Ctx); +} diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.h b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.h new file mode 100644 index 000000000000..26958ac8b9ee --- /dev/null +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.h @@ -0,0 +1,54 @@ +//===--- AMDGPUMCKernelDescriptor.h ---------------------------*- C++ -*---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// AMDHSA kernel descriptor MCExpr struct for use in MC layer. Uses +/// AMDHSAKernelDescriptor.h for sizes and constants. +/// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELDESCRIPTOR_H +#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELDESCRIPTOR_H + +#include "llvm/Support/AMDHSAKernelDescriptor.h" + +namespace llvm { +class MCExpr; +class MCContext; +class MCSubtargetInfo; +namespace AMDGPU { + +struct MCKernelDescriptor { + const MCExpr *group_segment_fixed_size = nullptr; + const MCExpr *private_segment_fixed_size = nullptr; + const MCExpr *kernarg_size = nullptr; + const MCExpr *compute_pgm_rsrc3 = nullptr; + const MCExpr *compute_pgm_rsrc1 = nullptr; + const MCExpr *compute_pgm_rsrc2 = nullptr; + const MCExpr *kernel_code_properties = nullptr; + const MCExpr *kernarg_preload = nullptr; + + static MCKernelDescriptor + getDefaultAmdhsaKernelDescriptor(const MCSubtargetInfo *STI, MCContext &Ctx); + // MCExpr for: + // Dst = Dst & ~Mask + // Dst = Dst | (Value << Shift) + static void bits_set(const MCExpr *&Dst, const MCExpr *Value, uint32_t Shift, + uint32_t Mask, MCContext &Ctx); + + // MCExpr for: + // return (Src & Mask) >> Shift + static const MCExpr *bits_get(const MCExpr *Src, uint32_t Shift, + uint32_t Mask, MCContext &Ctx); +}; + +} // end namespace AMDGPU +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELDESCRIPTOR_H diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp index 4742b0b3e52e..3006fcdb9282 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "AMDGPUTargetStreamer.h" +#include "AMDGPUMCKernelDescriptor.h" #include "AMDGPUPTNote.h" #include "AMDKernelCodeT.h" #include "Utils/AMDGPUBaseInfo.h" @@ -307,94 +308,142 @@ bool AMDGPUTargetAsmStreamer::EmitCodeEnd(const MCSubtargetInfo &STI) { void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor( const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KD, uint64_t NextVGPR, uint64_t NextSGPR, + const MCKernelDescriptor &KD, uint64_t NextVGPR, uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) { IsaVersion IVersion = getIsaVersion(STI.getCPU()); + const MCAsmInfo *MAI = getContext().getAsmInfo(); OS << "\t.amdhsa_kernel " << KernelName << '\n'; -#define PRINT_FIELD(STREAM, DIRECTIVE, KERNEL_DESC, MEMBER_NAME, FIELD_NAME) \ - STREAM << "\t\t" << DIRECTIVE << " " \ - << AMDHSA_BITS_GET(KERNEL_DESC.MEMBER_NAME, FIELD_NAME) << '\n'; - - OS << "\t\t.amdhsa_group_segment_fixed_size " << KD.group_segment_fixed_size - << '\n'; - OS << "\t\t.amdhsa_private_segment_fixed_size " - << KD.private_segment_fixed_size << '\n'; - OS << "\t\t.amdhsa_kernarg_size " << KD.kernarg_size << '\n'; - - PRINT_FIELD(OS, ".amdhsa_user_sgpr_count", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_USER_SGPR_COUNT); + auto PrintField = [&](const MCExpr *Expr, uint32_t Shift, uint32_t Mask, + StringRef Directive) { + int64_t IVal; + OS << "\t\t" << Directive << ' '; + const MCExpr *pgm_rsrc1_bits = + MCKernelDescriptor::bits_get(Expr, Shift, Mask, getContext()); + if (pgm_rsrc1_bits->evaluateAsAbsolute(IVal)) + OS << static_cast(IVal); + else + pgm_rsrc1_bits->print(OS, MAI); + OS << '\n'; + }; + + OS << "\t\t.amdhsa_group_segment_fixed_size "; + KD.group_segment_fixed_size->print(OS, MAI); + OS << '\n'; + + OS << "\t\t.amdhsa_private_segment_fixed_size "; + KD.private_segment_fixed_size->print(OS, MAI); + OS << '\n'; + + OS << "\t\t.amdhsa_kernarg_size "; + KD.kernarg_size->print(OS, MAI); + OS << '\n'; + + PrintField( + KD.compute_pgm_rsrc2, amdhsa::COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, ".amdhsa_user_sgpr_count"); if (!hasArchitectedFlatScratch(STI)) - PRINT_FIELD( - OS, ".amdhsa_user_sgpr_private_segment_buffer", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_dispatch_ptr", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_queue_ptr", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_kernarg_segment_ptr", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_dispatch_id", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID); + PrintField( + KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, + ".amdhsa_user_sgpr_private_segment_buffer"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, + ".amdhsa_user_sgpr_dispatch_ptr"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, + ".amdhsa_user_sgpr_queue_ptr"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR, + ".amdhsa_user_sgpr_kernarg_segment_ptr"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, + ".amdhsa_user_sgpr_dispatch_id"); if (!hasArchitectedFlatScratch(STI)) - PRINT_FIELD(OS, ".amdhsa_user_sgpr_flat_scratch_init", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, + ".amdhsa_user_sgpr_flat_scratch_init"); if (hasKernargPreload(STI)) { - PRINT_FIELD(OS, ".amdhsa_user_sgpr_kernarg_preload_length ", KD, - kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_LENGTH); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_kernarg_preload_offset ", KD, - kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_OFFSET); + PrintField(KD.kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_LENGTH_SHIFT, + amdhsa::KERNARG_PRELOAD_SPEC_LENGTH, + ".amdhsa_user_sgpr_kernarg_preload_length"); + PrintField(KD.kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_OFFSET_SHIFT, + amdhsa::KERNARG_PRELOAD_SPEC_OFFSET, + ".amdhsa_user_sgpr_kernarg_preload_offset"); } - PRINT_FIELD(OS, ".amdhsa_user_sgpr_private_segment_size", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE); + PrintField( + KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, + ".amdhsa_user_sgpr_private_segment_size"); if (IVersion.Major >= 10) - PRINT_FIELD(OS, ".amdhsa_wavefront_size32", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, + ".amdhsa_wavefront_size32"); if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) - PRINT_FIELD(OS, ".amdhsa_uses_dynamic_stack", KD, kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK); - PRINT_FIELD(OS, - (hasArchitectedFlatScratch(STI) - ? ".amdhsa_enable_private_segment" - : ".amdhsa_system_sgpr_private_segment_wavefront_offset"), - KD, compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_id_x", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_id_y", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_id_z", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_info", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO); - PRINT_FIELD(OS, ".amdhsa_system_vgpr_workitem_id", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, + ".amdhsa_uses_dynamic_stack"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, + (hasArchitectedFlatScratch(STI) + ? ".amdhsa_enable_private_segment" + : ".amdhsa_system_sgpr_private_segment_wavefront_offset")); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, + ".amdhsa_system_sgpr_workgroup_id_x"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, + ".amdhsa_system_sgpr_workgroup_id_y"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, + ".amdhsa_system_sgpr_workgroup_id_z"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, + ".amdhsa_system_sgpr_workgroup_info"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, + ".amdhsa_system_vgpr_workitem_id"); // These directives are required. OS << "\t\t.amdhsa_next_free_vgpr " << NextVGPR << '\n'; OS << "\t\t.amdhsa_next_free_sgpr " << NextSGPR << '\n'; - if (AMDGPU::isGFX90A(STI)) - OS << "\t\t.amdhsa_accum_offset " << - (AMDHSA_BITS_GET(KD.compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET) + 1) * 4 - << '\n'; + if (AMDGPU::isGFX90A(STI)) { + // MCExpr equivalent of taking the (accum_offset + 1) * 4. + const MCExpr *accum_bits = MCKernelDescriptor::bits_get( + KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, getContext()); + accum_bits = MCBinaryExpr::createAdd( + accum_bits, MCConstantExpr::create(1, getContext()), getContext()); + accum_bits = MCBinaryExpr::createMul( + accum_bits, MCConstantExpr::create(4, getContext()), getContext()); + OS << "\t\t.amdhsa_accum_offset "; + int64_t IVal; + if (accum_bits->evaluateAsAbsolute(IVal)) { + OS << static_cast(IVal); + } else { + accum_bits->print(OS, MAI); + } + OS << '\n'; + } if (!ReserveVCC) OS << "\t\t.amdhsa_reserve_vcc " << ReserveVCC << '\n'; @@ -411,74 +460,105 @@ void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor( break; } - PRINT_FIELD(OS, ".amdhsa_float_round_mode_32", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32); - PRINT_FIELD(OS, ".amdhsa_float_round_mode_16_64", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64); - PRINT_FIELD(OS, ".amdhsa_float_denorm_mode_32", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32); - PRINT_FIELD(OS, ".amdhsa_float_denorm_mode_16_64", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, + ".amdhsa_float_round_mode_32"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, + ".amdhsa_float_round_mode_16_64"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, + ".amdhsa_float_denorm_mode_32"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, + ".amdhsa_float_denorm_mode_16_64"); if (IVersion.Major < 12) { - PRINT_FIELD(OS, ".amdhsa_dx10_clamp", KD, compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP); - PRINT_FIELD(OS, ".amdhsa_ieee_mode", KD, compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, + ".amdhsa_dx10_clamp"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, + ".amdhsa_ieee_mode"); + } + if (IVersion.Major >= 9) { + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, + ".amdhsa_fp16_overflow"); } - if (IVersion.Major >= 9) - PRINT_FIELD(OS, ".amdhsa_fp16_overflow", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL); if (AMDGPU::isGFX90A(STI)) - PRINT_FIELD(OS, ".amdhsa_tg_split", KD, - compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT); + PrintField(KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, ".amdhsa_tg_split"); if (IVersion.Major >= 10) { - PRINT_FIELD(OS, ".amdhsa_workgroup_processor_mode", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE); - PRINT_FIELD(OS, ".amdhsa_memory_ordered", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED); - PRINT_FIELD(OS, ".amdhsa_forward_progress", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, + ".amdhsa_workgroup_processor_mode"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, + ".amdhsa_memory_ordered"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, + ".amdhsa_forward_progress"); } if (IVersion.Major >= 10 && IVersion.Major < 12) { - PRINT_FIELD(OS, ".amdhsa_shared_vgpr_count", KD, compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT); + PrintField(KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, + ".amdhsa_shared_vgpr_count"); } - if (IVersion.Major >= 12) - PRINT_FIELD(OS, ".amdhsa_round_robin_scheduling", KD, compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN); - PRINT_FIELD( - OS, ".amdhsa_exception_fp_ieee_invalid_op", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION); - PRINT_FIELD(OS, ".amdhsa_exception_fp_denorm_src", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE); - PRINT_FIELD( - OS, ".amdhsa_exception_fp_ieee_div_zero", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO); - PRINT_FIELD(OS, ".amdhsa_exception_fp_ieee_overflow", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW); - PRINT_FIELD(OS, ".amdhsa_exception_fp_ieee_underflow", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW); - PRINT_FIELD(OS, ".amdhsa_exception_fp_ieee_inexact", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT); - PRINT_FIELD(OS, ".amdhsa_exception_int_div_zero", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO); -#undef PRINT_FIELD + if (IVersion.Major >= 12) { + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, + ".amdhsa_round_robin_scheduling"); + } + PrintField( + KD.compute_pgm_rsrc2, + amdhsa:: + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, + ".amdhsa_exception_fp_ieee_invalid_op"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, + ".amdhsa_exception_fp_denorm_src"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa:: + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, + ".amdhsa_exception_fp_ieee_div_zero"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, + ".amdhsa_exception_fp_ieee_overflow"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, + ".amdhsa_exception_fp_ieee_underflow"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, + ".amdhsa_exception_fp_ieee_inexact"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, + ".amdhsa_exception_int_div_zero"); OS << "\t.end_amdhsa_kernel\n"; } @@ -835,7 +915,7 @@ bool AMDGPUTargetELFStreamer::EmitCodeEnd(const MCSubtargetInfo &STI) { void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor( const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, + const MCKernelDescriptor &KernelDescriptor, uint64_t NextVGPR, uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) { auto &Streamer = getStreamer(); auto &Context = Streamer.getContext(); @@ -853,7 +933,7 @@ void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor( // Kernel descriptor symbol's type and size are fixed. KernelDescriptorSymbol->setType(ELF::STT_OBJECT); KernelDescriptorSymbol->setSize( - MCConstantExpr::create(sizeof(KernelDescriptor), Context)); + MCConstantExpr::create(sizeof(amdhsa::kernel_descriptor_t), Context)); // The visibility of the kernel code symbol must be protected or less to allow // static relocations from the kernel descriptor to be used. @@ -861,31 +941,43 @@ void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor( KernelCodeSymbol->setVisibility(ELF::STV_PROTECTED); Streamer.emitLabel(KernelDescriptorSymbol); - Streamer.emitInt32(KernelDescriptor.group_segment_fixed_size); - Streamer.emitInt32(KernelDescriptor.private_segment_fixed_size); - Streamer.emitInt32(KernelDescriptor.kernarg_size); - - for (uint8_t Res : KernelDescriptor.reserved0) - Streamer.emitInt8(Res); + Streamer.emitValue( + KernelDescriptor.group_segment_fixed_size, + sizeof(amdhsa::kernel_descriptor_t::group_segment_fixed_size)); + Streamer.emitValue( + KernelDescriptor.private_segment_fixed_size, + sizeof(amdhsa::kernel_descriptor_t::private_segment_fixed_size)); + Streamer.emitValue(KernelDescriptor.kernarg_size, + sizeof(amdhsa::kernel_descriptor_t::kernarg_size)); + + for (uint32_t i = 0; i < sizeof(amdhsa::kernel_descriptor_t::reserved0); ++i) + Streamer.emitInt8(0u); // FIXME: Remove the use of VK_AMDGPU_REL64 in the expression below. The // expression being created is: // (start of kernel code) - (start of kernel descriptor) // It implies R_AMDGPU_REL64, but ends up being R_AMDGPU_ABS64. - Streamer.emitValue(MCBinaryExpr::createSub( - MCSymbolRefExpr::create( - KernelCodeSymbol, MCSymbolRefExpr::VK_AMDGPU_REL64, Context), - MCSymbolRefExpr::create( - KernelDescriptorSymbol, MCSymbolRefExpr::VK_None, Context), - Context), - sizeof(KernelDescriptor.kernel_code_entry_byte_offset)); - for (uint8_t Res : KernelDescriptor.reserved1) - Streamer.emitInt8(Res); - Streamer.emitInt32(KernelDescriptor.compute_pgm_rsrc3); - Streamer.emitInt32(KernelDescriptor.compute_pgm_rsrc1); - Streamer.emitInt32(KernelDescriptor.compute_pgm_rsrc2); - Streamer.emitInt16(KernelDescriptor.kernel_code_properties); - Streamer.emitInt16(KernelDescriptor.kernarg_preload); - for (uint8_t Res : KernelDescriptor.reserved3) - Streamer.emitInt8(Res); + Streamer.emitValue( + MCBinaryExpr::createSub( + MCSymbolRefExpr::create(KernelCodeSymbol, + MCSymbolRefExpr::VK_AMDGPU_REL64, Context), + MCSymbolRefExpr::create(KernelDescriptorSymbol, + MCSymbolRefExpr::VK_None, Context), + Context), + sizeof(amdhsa::kernel_descriptor_t::kernel_code_entry_byte_offset)); + for (uint32_t i = 0; i < sizeof(amdhsa::kernel_descriptor_t::reserved1); ++i) + Streamer.emitInt8(0u); + Streamer.emitValue(KernelDescriptor.compute_pgm_rsrc3, + sizeof(amdhsa::kernel_descriptor_t::compute_pgm_rsrc3)); + Streamer.emitValue(KernelDescriptor.compute_pgm_rsrc1, + sizeof(amdhsa::kernel_descriptor_t::compute_pgm_rsrc1)); + Streamer.emitValue(KernelDescriptor.compute_pgm_rsrc2, + sizeof(amdhsa::kernel_descriptor_t::compute_pgm_rsrc2)); + Streamer.emitValue( + KernelDescriptor.kernel_code_properties, + sizeof(amdhsa::kernel_descriptor_t::kernel_code_properties)); + Streamer.emitValue(KernelDescriptor.kernarg_preload, + sizeof(amdhsa::kernel_descriptor_t::kernarg_preload)); + for (uint32_t i = 0; i < sizeof(amdhsa::kernel_descriptor_t::reserved3); ++i) + Streamer.emitInt8(0u); } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h index 5aa80ff578c6..706897a5dc1f 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h @@ -22,15 +22,13 @@ class MCSymbol; class formatted_raw_ostream; namespace AMDGPU { + +struct MCKernelDescriptor; namespace HSAMD { struct Metadata; } } // namespace AMDGPU -namespace amdhsa { -struct kernel_descriptor_t; -} - class AMDGPUTargetStreamer : public MCTargetStreamer { AMDGPUPALMetadata PALMetadata; @@ -94,10 +92,11 @@ public: return true; } - virtual void EmitAmdhsaKernelDescriptor( - const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, - uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) {} + virtual void + EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName, + const AMDGPU::MCKernelDescriptor &KernelDescriptor, + uint64_t NextVGPR, uint64_t NextSGPR, + bool ReserveVCC, bool ReserveFlatScr) {} static StringRef getArchNameFromElfMach(unsigned ElfMach); static unsigned getElfMach(StringRef GPU); @@ -150,10 +149,11 @@ public: bool EmitKernargPreloadHeader(const MCSubtargetInfo &STI, bool TrapEnabled) override; - void EmitAmdhsaKernelDescriptor( - const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, - uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override; + void + EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName, + const AMDGPU::MCKernelDescriptor &KernelDescriptor, + uint64_t NextVGPR, uint64_t NextSGPR, + bool ReserveVCC, bool ReserveFlatScr) override; }; class AMDGPUTargetELFStreamer final : public AMDGPUTargetStreamer { @@ -205,10 +205,11 @@ public: bool EmitKernargPreloadHeader(const MCSubtargetInfo &STI, bool TrapEnabled) override; - void EmitAmdhsaKernelDescriptor( - const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, - uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override; + void + EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName, + const AMDGPU::MCKernelDescriptor &KernelDescriptor, + uint64_t NextVGPR, uint64_t NextSGPR, + bool ReserveVCC, bool ReserveFlatScr) override; }; } #endif diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt index 0842a58f794b..14a02b6d8e36 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt @@ -8,6 +8,7 @@ add_llvm_component_library(LLVMAMDGPUDesc AMDGPUMCExpr.cpp AMDGPUMCTargetDesc.cpp AMDGPUTargetStreamer.cpp + AMDGPUMCKernelDescriptor.cpp R600InstPrinter.cpp R600MCCodeEmitter.cpp R600MCTargetDesc.cpp diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp index 7bb84d78442b..5d44396b07b6 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -1221,47 +1221,6 @@ void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, } } -amdhsa::kernel_descriptor_t getDefaultAmdhsaKernelDescriptor( - const MCSubtargetInfo *STI) { - IsaVersion Version = getIsaVersion(STI->getCPU()); - - amdhsa::kernel_descriptor_t KD; - memset(&KD, 0, sizeof(KD)); - - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, - amdhsa::FLOAT_DENORM_MODE_FLUSH_NONE); - if (Version.Major >= 12) { - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, 0); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_DISABLE_PERF, 0); - } else { - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, 1); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, 1); - } - AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, 1); - if (Version.Major >= 10) { - AMDHSA_BITS_SET(KD.kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, - STI->getFeatureBits().test(FeatureWavefrontSize32) ? 1 : 0); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, - STI->getFeatureBits().test(FeatureCuMode) ? 0 : 1); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, 1); - } - if (AMDGPU::isGFX90A(*STI)) { - AMDHSA_BITS_SET(KD.compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, - STI->getFeatureBits().test(FeatureTgSplit) ? 1 : 0); - } - return KD; -} - bool isGroupSegment(const GlobalValue *GV) { return GV->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS; } diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h index f4f9a787100b..943588fe701c 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -34,10 +34,6 @@ class StringRef; class Triple; class raw_ostream; -namespace amdhsa { -struct kernel_descriptor_t; -} - namespace AMDGPU { struct IsaVersion; @@ -855,9 +851,6 @@ unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc); void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, const MCSubtargetInfo *STI); -amdhsa::kernel_descriptor_t getDefaultAmdhsaKernelDescriptor( - const MCSubtargetInfo *STI); - bool isGroupSegment(const GlobalValue *GV); bool isGlobalSegment(const GlobalValue *GV); bool isReadOnlySegment(const GlobalValue *GV); diff --git a/llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s b/llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s new file mode 100644 index 000000000000..4623500987be --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// OBJDUMP: 0000 00000000 0f000000 00000000 00000000 + +.text + +.p2align 8 +.type caller,@function +caller: + s_endpgm + +.rodata + +.p2align 6 +.amdhsa_kernel caller + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_private_segment_fixed_size max(7, callee1.private_seg_size, callee2.private_seg_size) +.end_amdhsa_kernel + +.set callee1.private_seg_size, 4 +.set callee2.private_seg_size, 15 + +// ASM: .amdhsa_private_segment_fixed_size max(7, callee1.private_seg_size, callee2.private_seg_size) diff --git a/llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s b/llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s new file mode 100644 index 000000000000..fab3e893352b --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s @@ -0,0 +1,281 @@ +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a %s 2>&1 | FileCheck --check-prefix=ASM %s + +// Some expression currently require (immediately) solvable expressions, i.e., +// they don't depend on yet-unknown symbolic values. + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type user_sgpr_count,@function +user_sgpr_count: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_count + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_count defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_count + +.p2align 8 +.type user_sgpr_private_segment_buffer,@function +user_sgpr_private_segment_buffer: + s_endpgm + +.amdhsa_kernel user_sgpr_private_segment_buffer + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_private_segment_buffer defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer + +.p2align 8 +.type user_sgpr_kernarg_preload_length,@function +user_sgpr_kernarg_preload_length: + s_endpgm + +.amdhsa_kernel user_sgpr_kernarg_preload_length + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_kernarg_preload_length defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length defined_boolean + +.p2align 8 +.type user_sgpr_kernarg_preload_offset,@function +user_sgpr_kernarg_preload_offset: + s_endpgm + +.amdhsa_kernel user_sgpr_kernarg_preload_offset + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_kernarg_preload_offset defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset defined_boolean + +.p2align 8 +.type user_sgpr_dispatch_ptr,@function +user_sgpr_dispatch_ptr: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_dispatch_ptr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_dispatch_ptr defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr + +.p2align 8 +.type user_sgpr_queue_ptr,@function +user_sgpr_queue_ptr: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_queue_ptr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_queue_ptr defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr + +.p2align 8 +.type user_sgpr_kernarg_segment_ptr,@function +user_sgpr_kernarg_segment_ptr: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_kernarg_segment_ptr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_kernarg_segment_ptr defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr + +.p2align 8 +.type user_sgpr_dispatch_id,@function +user_sgpr_dispatch_id: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_dispatch_id + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_dispatch_id defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id + +.p2align 8 +.type user_sgpr_flat_scratch_init,@function +user_sgpr_flat_scratch_init: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_flat_scratch_init + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_flat_scratch_init defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init + +.p2align 8 +.type user_sgpr_private_segment_size,@function +user_sgpr_private_segment_size: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_private_segment_size + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_private_segment_size defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size + +.p2align 8 +.type wavefront_size32,@function +wavefront_size32: + s_endpgm + +.p2align 6 +.amdhsa_kernel wavefront_size32 + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_wavefront_size32 defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_wavefront_size32 + +.p2align 8 +.type next_free_vgpr,@function +next_free_vgpr: + s_endpgm + +.p2align 6 +.amdhsa_kernel next_free_vgpr + .amdhsa_next_free_vgpr defined_boolean + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_next_free_vgpr + +.p2align 8 +.type next_free_sgpr,@function +next_free_sgpr: + s_endpgm + +.p2align 6 +.amdhsa_kernel next_free_sgpr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr defined_boolean + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_next_free_sgpr + +.p2align 8 +.type accum_offset,@function +accum_offset: + s_endpgm + +.p2align 6 +.amdhsa_kernel accum_offset + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_accum_offset + +.p2align 8 +.type reserve_vcc,@function +reserve_vcc: + s_endpgm + +.p2align 6 +.amdhsa_kernel reserve_vcc + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_reserve_vcc defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_reserve_vcc + +.p2align 8 +.type reserve_flat_scratch,@function +reserve_flat_scratch: + s_endpgm + +.p2align 6 +.amdhsa_kernel reserve_flat_scratch + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_reserve_flat_scratch defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_reserve_flat_scratch + +.p2align 8 +.type shared_vgpr_count,@function +shared_vgpr_count: + s_endpgm + +.p2align 6 +.amdhsa_kernel shared_vgpr_count + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_shared_vgpr_count defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_shared_vgpr_count + +.set defined_boolean, 1 + +// ASM: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s new file mode 100644 index 000000000000..95af59c413ae --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s @@ -0,0 +1,190 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1010 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1010 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0afe4 801f007f 000c0000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0afe4 801f007f 000c0000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1)>>0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&32)>>5 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_wavefront_size32 (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1024)>>10 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_workgroup_processor_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&536870912)>>29 +// ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&1073741824)>>30 +// ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2147483648)>>31 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_wavefront_size32 1 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_workgroup_processor_mode 1 +// ASM-NEXT: .amdhsa_memory_ordered 1 +// ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s new file mode 100644 index 000000000000..e1107fb69ba4 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s @@ -0,0 +1,186 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1100 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1100 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0afe4 811f007f 000c0000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0afe4 811f007f 000c0000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_wavefront_size32 (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1024)>>10 +// ASM-NEXT: .amdhsa_enable_private_segment (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_workgroup_processor_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&536870912)>>29 +// ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&1073741824)>>30 +// ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2147483648)>>31 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_wavefront_size32 1 +// ASM-NEXT: .amdhsa_enable_private_segment 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_workgroup_processor_mode 1 +// ASM-NEXT: .amdhsa_memory_ordered 1 +// ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s new file mode 100644 index 000000000000..449616d35186 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s @@ -0,0 +1,184 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1200 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1200 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f02fe4 811f007f 000c0000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f02fe4 811f007f 000c0000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_round_robin_scheduling defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_round_robin_scheduling defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_wavefront_size32 (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1024)>>10 +// ASM-NEXT: .amdhsa_enable_private_segment (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_workgroup_processor_mode (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&536870912)>>29 +// ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&1073741824)>>30 +// ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&2147483648)>>31 +// ASM-NEXT: .amdhsa_round_robin_scheduling (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_wavefront_size32 1 +// ASM-NEXT: .amdhsa_enable_private_segment 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_workgroup_processor_mode 1 +// ASM-NEXT: .amdhsa_memory_ordered 1 +// ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_round_robin_scheduling 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s new file mode 100644 index 000000000000..c7e05441b45f --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s @@ -0,0 +1,168 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx700 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx700 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0af00 801f007f 00080000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0af00 801f007f 00080000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer (((0&(~2048))|(defined_boolean<<11))&1)>>0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((0&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((0&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((0&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((0&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init (((0&(~2048))|(defined_boolean<<11))&32)>>5 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((0&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s new file mode 100644 index 000000000000..49a5015987a6 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s @@ -0,0 +1,171 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx801 < %s | FileCheck --check-prefix=ASM %s + +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx801 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0af00 801f007f 00080000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0af00 801f007f 00080000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer (((0&(~2048))|(defined_boolean<<11))&1)>>0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((0&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((0&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((0&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((0&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init (((0&(~2048))|(defined_boolean<<11))&32)>>5 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((0&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s new file mode 100644 index 000000000000..b7f89239160f --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s @@ -0,0 +1,148 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000100 +// OBJDUMP-NEXT: 0030 0000ac04 81000000 00000000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000100 +// OBJDUMP-NEXT: 0070 0000ac04 81000000 00000000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_system_sgpr_private_segment_wavefront_offset defined_boolean + .amdhsa_dx10_clamp defined_boolean + .amdhsa_ieee_mode defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_tg_split defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_system_sgpr_private_segment_wavefront_offset defined_boolean + .amdhsa_dx10_clamp defined_boolean + .amdhsa_ieee_mode defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_tg_split defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_accum_offset (((((((0&(~65536))|(defined_boolean<<16))&(~63))|(0<<0))&63)>>0)+1)*4 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_tg_split (((((0&(~65536))|(defined_boolean<<16))&(~63))|(0<<0))&65536)>>16 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 0 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 0 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_accum_offset 4 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 0 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_tg_split 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 0 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 0 +// ASM-NEXT: .amdhsa_exception_int_div_zero 0 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-tg-split.s b/llvm/test/MC/AMDGPU/hsa-tg-split.s new file mode 100644 index 000000000000..5a4d3e2c279c --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-tg-split.s @@ -0,0 +1,74 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -mattr=+xnack,+tgsplit < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -mattr=+xnack,+tgsplit -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// OBJDUMP: Contents of section .rodata +// OBJDUMP-NEXT: 0000 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000100 +// OBJDUMP-NEXT: 0030 0000ac00 80000000 00000000 00000000 + +.text +// ASM: .text + +.amdgcn_target "amdgcn-amd-amdhsa--gfx90a:xnack+" +// ASM: .amdgcn_target "amdgcn-amd-amdhsa--gfx90a:xnack+" + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type minimal,@function +minimal: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel minimal + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel minimal +// ASM-NEXT: .amdhsa_group_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 0 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 0 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_accum_offset 4 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 0 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 0 +// ASM-NEXT: .amdhsa_tg_split 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 0 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 0 +// ASM-NEXT: .amdhsa_exception_int_div_zero 0 +// ASM-NEXT: .end_amdhsa_kernel -- GitLab From 408c36522f7eb8638314b584995daf5790968842 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 27 Mar 2024 12:00:32 +0000 Subject: [PATCH 049/541] [gn build] Port 1103a2a337e9 --- .../gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn index 12d875cf40c9..5ba91fcec83a 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn @@ -104,6 +104,7 @@ static_library("MCTargetDesc") { "AMDGPUMCAsmInfo.cpp", "AMDGPUMCCodeEmitter.cpp", "AMDGPUMCExpr.cpp", + "AMDGPUMCKernelDescriptor.cpp", "AMDGPUMCTargetDesc.cpp", "AMDGPUTargetStreamer.cpp", "R600InstPrinter.cpp", -- GitLab From 51388fbab1b9454dfe24c4ac1c8b4a009162386a Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 26 Mar 2024 18:37:15 +0000 Subject: [PATCH 050/541] [DAG] visitSub - reuse existing SDLoc instead of regenerating it. NFC. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 39ee95d7007c..a021e0e19fc3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3884,7 +3884,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (SDValue V = foldSubToAvg(N, DL)) return V; - if (SDValue V = foldAddSubMasked1(false, N0, N1, DAG, SDLoc(N))) + if (SDValue V = foldAddSubMasked1(false, N0, N1, DAG, DL)) return V; if (SDValue V = foldSubToUSubSat(VT, N, DL)) @@ -3949,7 +3949,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if ((X0 == S0 && X1 == N1) || (X0 == N1 && X1 == S0)) if (ConstantSDNode *C = isConstOrConstSplat(N1.getOperand(1))) if (C->getAPIntValue() == (BitWidth - 1)) - return DAG.getNode(ISD::ABS, SDLoc(N), VT, S0); + return DAG.getNode(ISD::ABS, DL, VT, S0); } } -- GitLab From 9247f3185c7e1f7a2c1071fa61e283deb21091aa Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 26 Mar 2024 18:41:47 +0000 Subject: [PATCH 051/541] [DAG] foldAddSubOfSignBit - reuse existing SDLoc instead of regenerating it. NFC. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a021e0e19fc3..36abe27d2621 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2555,7 +2555,8 @@ SDValue DAGCombiner::foldSubToAvg(SDNode *N, const SDLoc &DL) { /// Try to fold a 'not' shifted sign-bit with add/sub with constant operand into /// a shift and add with a different constant. -static SDValue foldAddSubOfSignBit(SDNode *N, SelectionDAG &DAG) { +static SDValue foldAddSubOfSignBit(SDNode *N, const SDLoc &DL, + SelectionDAG &DAG) { assert((N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && "Expecting add or sub"); @@ -2583,7 +2584,6 @@ static SDValue foldAddSubOfSignBit(SDNode *N, SelectionDAG &DAG) { // Eliminate the 'not' by adjusting the shift and add/sub constant: // add (srl (not X), 31), C --> add (sra X, 31), (C + 1) // sub C, (srl (not X), 31) --> add (srl X, 31), (C - 1) - SDLoc DL(N); if (SDValue NewC = DAG.FoldConstantArithmetic( IsAdd ? ISD::ADD : ISD::SUB, DL, VT, {ConstantOp, DAG.getConstant(1, DL, VT)})) { @@ -2878,7 +2878,7 @@ SDValue DAGCombiner::visitADD(SDNode *N) { if (SDValue V = foldAddSubBoolOfMaskedVal(N, DL, DAG)) return V; - if (SDValue V = foldAddSubOfSignBit(N, DAG)) + if (SDValue V = foldAddSubOfSignBit(N, DL, DAG)) return V; // Try to match AVGFLOOR fixedwidth pattern @@ -3877,7 +3877,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (SDValue V = foldAddSubBoolOfMaskedVal(N, DL, DAG)) return V; - if (SDValue V = foldAddSubOfSignBit(N, DAG)) + if (SDValue V = foldAddSubOfSignBit(N, DL, DAG)) return V; // Try to match AVGCEIL fixedwidth pattern -- GitLab From 875aed17b978bf58a01d31572af6964e91a9f641 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 12:13:03 +0000 Subject: [PATCH 052/541] [X86] Add combineExtractFromVectorLoad helper - pulled out of combineExtractVectorElt Prep work for #85419 to make it easier to reuse in other combines --- llvm/lib/Target/X86/X86ISelLowering.cpp | 78 ++++++++++++++++--------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 9bad38f97c6a..4cd0bebe01bb 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -43995,6 +43995,49 @@ static SDValue combineBasicSADPattern(SDNode *Extract, SelectionDAG &DAG, Extract->getOperand(1)); } +// If this extract is from a loaded vector value and will be used as an +// integer, that requires a potentially expensive XMM -> GPR transfer. +// Additionally, if we can convert to a scalar integer load, that will likely +// be folded into a subsequent integer op. +// Note: Unlike the related fold for this in DAGCombiner, this is not limited +// to a single-use of the loaded vector. For the reasons above, we +// expect this to be profitable even if it creates an extra load. +static SDValue +combineExtractFromVectorLoad(SDNode *N, SDValue InputVector, uint64_t Idx, + const SDLoc &dl, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI) { + assert(N->getOpcode() == ISD::EXTRACT_VECTOR_ELT && + "Only EXTRACT_VECTOR_ELT supported so far"); + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + EVT SrcVT = InputVector.getValueType(); + EVT VT = N->getValueType(0); + + bool LikelyUsedAsVector = any_of(N->uses(), [](SDNode *Use) { + return Use->getOpcode() == ISD::STORE || + Use->getOpcode() == ISD::INSERT_VECTOR_ELT || + Use->getOpcode() == ISD::SCALAR_TO_VECTOR; + }); + + auto *LoadVec = dyn_cast(InputVector); + if (LoadVec && ISD::isNormalLoad(LoadVec) && VT.isInteger() && + SrcVT.getVectorElementType() == VT && DCI.isAfterLegalizeDAG() && + !LikelyUsedAsVector && LoadVec->isSimple()) { + SDValue NewPtr = TLI.getVectorElementPointer( + DAG, LoadVec->getBasePtr(), SrcVT, DAG.getVectorIdxConstant(Idx, dl)); + unsigned PtrOff = VT.getSizeInBits() * Idx / 8; + MachinePointerInfo MPI = LoadVec->getPointerInfo().getWithOffset(PtrOff); + Align Alignment = commonAlignment(LoadVec->getAlign(), PtrOff); + SDValue Load = + DAG.getLoad(VT, dl, LoadVec->getChain(), NewPtr, MPI, Alignment, + LoadVec->getMemOperand()->getFlags(), LoadVec->getAAInfo()); + DAG.makeEquivalentMemoryOrdering(LoadVec, Load); + return Load; + } + + return SDValue(); +} + // Attempt to peek through a target shuffle and extract the scalar from the // source. static SDValue combineExtractWithShuffle(SDNode *N, SelectionDAG &DAG, @@ -44600,6 +44643,11 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG, if (SDValue V = scalarizeExtEltFP(N, DAG, Subtarget)) return V; + if (CIdx) + if (SDValue V = combineExtractFromVectorLoad( + N, InputVector, CIdx->getZExtValue(), dl, DAG, DCI)) + return V; + // Attempt to extract a i1 element by using MOVMSK to extract the signbits // and then testing the relevant element. // @@ -44645,34 +44693,6 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG, } } - // If this extract is from a loaded vector value and will be used as an - // integer, that requires a potentially expensive XMM -> GPR transfer. - // Additionally, if we can convert to a scalar integer load, that will likely - // be folded into a subsequent integer op. - // Note: Unlike the related fold for this in DAGCombiner, this is not limited - // to a single-use of the loaded vector. For the reasons above, we - // expect this to be profitable even if it creates an extra load. - bool LikelyUsedAsVector = any_of(N->uses(), [](SDNode *Use) { - return Use->getOpcode() == ISD::STORE || - Use->getOpcode() == ISD::INSERT_VECTOR_ELT || - Use->getOpcode() == ISD::SCALAR_TO_VECTOR; - }); - auto *LoadVec = dyn_cast(InputVector); - if (LoadVec && CIdx && ISD::isNormalLoad(LoadVec) && VT.isInteger() && - SrcVT.getVectorElementType() == VT && DCI.isAfterLegalizeDAG() && - !LikelyUsedAsVector && LoadVec->isSimple()) { - SDValue NewPtr = - TLI.getVectorElementPointer(DAG, LoadVec->getBasePtr(), SrcVT, EltIdx); - unsigned PtrOff = VT.getSizeInBits() * CIdx->getZExtValue() / 8; - MachinePointerInfo MPI = LoadVec->getPointerInfo().getWithOffset(PtrOff); - Align Alignment = commonAlignment(LoadVec->getAlign(), PtrOff); - SDValue Load = - DAG.getLoad(VT, dl, LoadVec->getChain(), NewPtr, MPI, Alignment, - LoadVec->getMemOperand()->getFlags(), LoadVec->getAAInfo()); - DAG.makeEquivalentMemoryOrdering(LoadVec, Load); - return Load; - } - return SDValue(); } @@ -48273,7 +48293,7 @@ static SDValue combineAndShuffleNot(SDNode *N, SelectionDAG &DAG, // We do not split for SSE at all, but we need to split vectors for AVX1 and // AVX2. - if (!Subtarget.useAVX512Regs() && VT.is512BitVector() && + if (!Subtarget.useAVX512Regs() && VT.is512BitVector() && TLI.isTypeLegal(VT.getHalfNumVectorElementsVT(*DAG.getContext()))) { SDValue LoX, HiX; std::tie(LoX, HiX) = splitVector(X, DAG, DL); -- GitLab From e82765bf07a978674c0e75c8b2e20f154ae24a4c Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 12:18:54 +0000 Subject: [PATCH 053/541] [X86] masked_store.ll - add nounwind to remove cfi noise --- llvm/test/CodeGen/X86/masked_store.ll | 79 +++++++++++---------------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/llvm/test/CodeGen/X86/masked_store.ll b/llvm/test/CodeGen/X86/masked_store.ll index 898b34e969b1..03245ea31730 100644 --- a/llvm/test/CodeGen/X86/masked_store.ll +++ b/llvm/test/CodeGen/X86/masked_store.ll @@ -12,7 +12,7 @@ ; vXf64 ; -define void @store_v1f64_v1i64(<1 x i64> %trigger, ptr %addr, <1 x double> %val) { +define void @store_v1f64_v1i64(<1 x i64> %trigger, ptr %addr, <1 x double> %val) nounwind { ; SSE-LABEL: store_v1f64_v1i64: ; SSE: ## %bb.0: ; SSE-NEXT: testq %rdi, %rdi @@ -46,7 +46,7 @@ define void @store_v1f64_v1i64(<1 x i64> %trigger, ptr %addr, <1 x double> %val) ret void } -define void @store_v2f64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x double> %val) { +define void @store_v2f64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x double> %val) nounwind { ; SSE-LABEL: store_v2f64_v2i64: ; SSE: ## %bb.0: ; SSE-NEXT: movmskpd %xmm0, %eax @@ -106,7 +106,7 @@ define void @store_v2f64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x double> %val) ret void } -define void @store_v4f64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x double> %val) { +define void @store_v4f64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x double> %val) nounwind { ; SSE2-LABEL: store_v4f64_v4i64: ; SSE2: ## %bb.0: ; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] @@ -222,7 +222,7 @@ define void @store_v4f64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x double> %val) ; vXf32 ; -define void @store_v2f32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x float> %val) { +define void @store_v2f32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x float> %val) nounwind { ; SSE2-LABEL: store_v2f32_v2i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,0,1,1] @@ -314,7 +314,7 @@ define void @store_v2f32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x float> %val) ret void } -define void @store_v4f32_v4i32(<4 x float> %x, ptr %ptr, <4 x float> %y, <4 x i32> %mask) { +define void @store_v4f32_v4i32(<4 x float> %x, ptr %ptr, <4 x float> %y, <4 x i32> %mask) nounwind { ; SSE2-LABEL: store_v4f32_v4i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskps %xmm2, %eax @@ -425,7 +425,7 @@ define void @store_v4f32_v4i32(<4 x float> %x, ptr %ptr, <4 x float> %y, <4 x i3 ret void } -define void @store_v8f32_v8i32(<8 x float> %x, ptr %ptr, <8 x float> %y, <8 x i32> %mask) { +define void @store_v8f32_v8i32(<8 x float> %x, ptr %ptr, <8 x float> %y, <8 x i32> %mask) nounwind { ; SSE2-LABEL: store_v8f32_v8i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: packssdw %xmm5, %xmm4 @@ -605,7 +605,7 @@ define void @store_v8f32_v8i32(<8 x float> %x, ptr %ptr, <8 x float> %y, <8 x i3 ret void } -define void @store_v16f32_v16i32(<16 x float> %x, ptr %ptr, <16 x float> %y, <16 x i32> %mask) { +define void @store_v16f32_v16i32(<16 x float> %x, ptr %ptr, <16 x float> %y, <16 x i32> %mask) nounwind { ; SSE2-LABEL: store_v16f32_v16i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm4 @@ -914,7 +914,7 @@ define void @store_v16f32_v16i32(<16 x float> %x, ptr %ptr, <16 x float> %y, <16 ; vXi64 ; -define void @store_v2i64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x i64> %val) { +define void @store_v2i64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x i64> %val) nounwind { ; SSE2-LABEL: store_v2i64_v2i64: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskpd %xmm0, %eax @@ -998,7 +998,7 @@ define void @store_v2i64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x i64> %val) { ret void } -define void @store_v4i64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x i64> %val) { +define void @store_v4i64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x i64> %val) nounwind { ; SSE2-LABEL: store_v4i64_v4i64: ; SSE2: ## %bb.0: ; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] @@ -1122,7 +1122,7 @@ define void @store_v4i64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x i64> %val) { ; vXi32 ; -define void @store_v1i32_v1i32(<1 x i32> %trigger, ptr %addr, <1 x i32> %val) { +define void @store_v1i32_v1i32(<1 x i32> %trigger, ptr %addr, <1 x i32> %val) nounwind { ; SSE-LABEL: store_v1i32_v1i32: ; SSE: ## %bb.0: ; SSE-NEXT: testl %edi, %edi @@ -1156,7 +1156,7 @@ define void @store_v1i32_v1i32(<1 x i32> %trigger, ptr %addr, <1 x i32> %val) { ret void } -define void @store_v2i32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x i32> %val) { +define void @store_v2i32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x i32> %val) nounwind { ; SSE2-LABEL: store_v2i32_v2i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,0,1,1] @@ -1256,7 +1256,7 @@ define void @store_v2i32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x i32> %val) { ret void } -define void @store_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) { +define void @store_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) nounwind { ; SSE2-LABEL: store_v4i32_v4i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm2, %xmm2 @@ -1370,7 +1370,7 @@ define void @store_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) { ret void } -define void @store_v8i32_v8i32(<8 x i32> %trigger, ptr %addr, <8 x i32> %val) { +define void @store_v8i32_v8i32(<8 x i32> %trigger, ptr %addr, <8 x i32> %val) nounwind { ; SSE2-LABEL: store_v8i32_v8i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm4, %xmm4 @@ -1560,7 +1560,7 @@ define void @store_v8i32_v8i32(<8 x i32> %trigger, ptr %addr, <8 x i32> %val) { ; vXi16 ; -define void @store_v8i16_v8i16(<8 x i16> %trigger, ptr %addr, <8 x i16> %val) { +define void @store_v8i16_v8i16(<8 x i16> %trigger, ptr %addr, <8 x i16> %val) nounwind { ; SSE2-LABEL: store_v8i16_v8i16: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm2, %xmm2 @@ -1907,7 +1907,7 @@ define void @store_v8i16_v8i16(<8 x i16> %trigger, ptr %addr, <8 x i16> %val) { ret void } -define void @store_v16i16_v16i16(<16 x i16> %trigger, ptr %addr, <16 x i16> %val) { +define void @store_v16i16_v16i16(<16 x i16> %trigger, ptr %addr, <16 x i16> %val) nounwind { ; SSE2-LABEL: store_v16i16_v16i16: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm4, %xmm4 @@ -2676,7 +2676,7 @@ define void @store_v16i16_v16i16(<16 x i16> %trigger, ptr %addr, <16 x i16> %val ; vXi8 ; -define void @store_v16i8_v16i8(<16 x i8> %trigger, ptr %addr, <16 x i8> %val) { +define void @store_v16i8_v16i8(<16 x i8> %trigger, ptr %addr, <16 x i8> %val) nounwind { ; SSE2-LABEL: store_v16i8_v16i8: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm2, %xmm2 @@ -3273,7 +3273,7 @@ define void @store_v16i8_v16i8(<16 x i8> %trigger, ptr %addr, <16 x i8> %val) { ret void } -define void @store_v32i8_v32i8(<32 x i8> %trigger, ptr %addr, <32 x i8> %val) { +define void @store_v32i8_v32i8(<32 x i8> %trigger, ptr %addr, <32 x i8> %val) nounwind { ; SSE2-LABEL: store_v32i8_v32i8: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm4, %xmm4 @@ -4670,7 +4670,7 @@ define void @store_v32i8_v32i8(<32 x i8> %trigger, ptr %addr, <32 x i8> %val) { ;;; Stores with Constant Masks -define void @mstore_constmask_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) { +define void @mstore_constmask_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) nounwind { ; SSE-LABEL: mstore_constmask_v4i32_v4i32: ; SSE: ## %bb.0: ; SSE-NEXT: movups %xmm1, (%rdi) @@ -4693,7 +4693,7 @@ define void @mstore_constmask_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i3 ; Make sure we are able to detect all ones constant mask after type legalization ; to avoid masked stores. -define void @mstore_constmask_allones_split(<16 x i64> %trigger, ptr %addr, <16 x i64> %val) { +define void @mstore_constmask_allones_split(<16 x i64> %trigger, ptr %addr, <16 x i64> %val) nounwind { ; SSE2-LABEL: mstore_constmask_allones_split: ; SSE2: ## %bb.0: ; SSE2-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm0 @@ -4810,7 +4810,7 @@ define void @mstore_constmask_allones_split(<16 x i64> %trigger, ptr %addr, <16 ; When only one element of the mask is set, reduce to a scalar store. -define void @one_mask_bit_set1(ptr %addr, <4 x i32> %val) { +define void @one_mask_bit_set1(ptr %addr, <4 x i32> %val) nounwind { ; SSE-LABEL: one_mask_bit_set1: ; SSE: ## %bb.0: ; SSE-NEXT: movss %xmm0, (%rdi) @@ -4832,7 +4832,7 @@ define void @one_mask_bit_set1(ptr %addr, <4 x i32> %val) { ; Choose a different element to show that the correct address offset is produced. -define void @one_mask_bit_set2(ptr %addr, <4 x float> %val) { +define void @one_mask_bit_set2(ptr %addr, <4 x float> %val) nounwind { ; SSE2-LABEL: one_mask_bit_set2: ; SSE2: ## %bb.0: ; SSE2-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1] @@ -4860,7 +4860,7 @@ define void @one_mask_bit_set2(ptr %addr, <4 x float> %val) { ; Choose a different scalar type and a high element of a 256-bit vector because AVX doesn't support those evenly. -define void @one_mask_bit_set3(ptr %addr, <4 x i64> %val) { +define void @one_mask_bit_set3(ptr %addr, <4 x i64> %val) nounwind { ; SSE-LABEL: one_mask_bit_set3: ; SSE: ## %bb.0: ; SSE-NEXT: movlps %xmm1, 16(%rdi) @@ -4886,7 +4886,7 @@ define void @one_mask_bit_set3(ptr %addr, <4 x i64> %val) { ; Choose a different scalar type and a high element of a 256-bit vector because AVX doesn't support those evenly. -define void @one_mask_bit_set4(ptr %addr, <4 x double> %val) { +define void @one_mask_bit_set4(ptr %addr, <4 x double> %val) nounwind { ; SSE-LABEL: one_mask_bit_set4: ; SSE: ## %bb.0: ; SSE-NEXT: movhps %xmm1, 24(%rdi) @@ -4912,7 +4912,7 @@ define void @one_mask_bit_set4(ptr %addr, <4 x double> %val) { ; Try a 512-bit vector to make sure AVX doesn't die and AVX512 works as expected. -define void @one_mask_bit_set5(ptr %addr, <8 x double> %val) { +define void @one_mask_bit_set5(ptr %addr, <8 x double> %val) nounwind { ; SSE-LABEL: one_mask_bit_set5: ; SSE: ## %bb.0: ; SSE-NEXT: movlps %xmm3, 48(%rdi) @@ -4944,7 +4944,7 @@ define void @one_mask_bit_set5(ptr %addr, <8 x double> %val) { } ; Try one elt in each half of a vector that needs to split -define void @one_mask_bit_set6(ptr %addr, <16 x i64> %val) { +define void @one_mask_bit_set6(ptr %addr, <16 x i64> %val) nounwind { ; SSE2-LABEL: one_mask_bit_set6: ; SSE2: ## %bb.0: ; SSE2-NEXT: movlps %xmm3, 48(%rdi) @@ -4999,7 +4999,7 @@ define void @one_mask_bit_set6(ptr %addr, <16 x i64> %val) { ret void } -define void @top_bits_unset_stack() { +define void @top_bits_unset_stack() nounwind { ; SSE-LABEL: top_bits_unset_stack: ; SSE: ## %bb.0: ## %entry ; SSE-NEXT: xorps %xmm0, %xmm0 @@ -5047,7 +5047,6 @@ define void @top_bits_unset_stack() { ; X86-AVX512-LABEL: top_bits_unset_stack: ; X86-AVX512: ## %bb.0: ## %entry ; X86-AVX512-NEXT: subl $76, %esp -; X86-AVX512-NEXT: .cfi_def_cfa_offset 80 ; X86-AVX512-NEXT: vxorpd %xmm0, %xmm0, %xmm0 ; X86-AVX512-NEXT: movb $63, %al ; X86-AVX512-NEXT: kmovd %eax, %k1 @@ -5064,7 +5063,7 @@ entry: ; SimplifyDemandedBits eliminates an ashr here. -define void @masked_store_bool_mask_demand_trunc_sext(<4 x double> %x, ptr %p, <4 x i32> %masksrc) { +define void @masked_store_bool_mask_demand_trunc_sext(<4 x double> %x, ptr %p, <4 x i32> %masksrc) nounwind { ; SSE-LABEL: masked_store_bool_mask_demand_trunc_sext: ; SSE: ## %bb.0: ; SSE-NEXT: pslld $31, %xmm2 @@ -5160,7 +5159,7 @@ define void @masked_store_bool_mask_demand_trunc_sext(<4 x double> %x, ptr %p, < ; PR26697 -define void @one_mask_bit_set1_variable(ptr %addr, <4 x float> %val, <4 x i32> %mask) { +define void @one_mask_bit_set1_variable(ptr %addr, <4 x float> %val, <4 x i32> %mask) nounwind { ; SSE2-LABEL: one_mask_bit_set1_variable: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskps %xmm1, %eax @@ -5267,7 +5266,7 @@ define void @one_mask_bit_set1_variable(ptr %addr, <4 x float> %val, <4 x i32> % ; This needs to be widened to v4i32. ; This used to assert in type legalization. PR38436 ; FIXME: The codegen for AVX512 should use KSHIFT to zero the upper bits of the mask. -define void @widen_masked_store(<3 x i32> %v, ptr %p, <3 x i1> %mask) { +define void @widen_masked_store(<3 x i32> %v, ptr %p, <3 x i1> %mask) nounwind { ; SSE2-LABEL: widen_masked_store: ; SSE2: ## %bb.0: ; SSE2-NEXT: andb $1, %sil @@ -5448,7 +5447,7 @@ define void @widen_masked_store(<3 x i32> %v, ptr %p, <3 x i1> %mask) { ret void } -define void @zero_mask(ptr %addr, <2 x double> %val) { +define void @zero_mask(ptr %addr, <2 x double> %val) nounwind { ; SSE-LABEL: zero_mask: ; SSE: ## %bb.0: ; SSE-NEXT: retq @@ -5464,7 +5463,7 @@ define void @zero_mask(ptr %addr, <2 x double> %val) { ret void } -define void @PR11210(<4 x float> %x, ptr %ptr, <4 x float> %y, <2 x i64> %mask) { +define void @PR11210(<4 x float> %x, ptr %ptr, <4 x float> %y, <2 x i64> %mask) nounwind { ; SSE2-LABEL: PR11210: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskps %xmm2, %eax @@ -5638,7 +5637,7 @@ define void @PR11210(<4 x float> %x, ptr %ptr, <4 x float> %y, <2 x i64> %mask) ret void } -define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigger.ptr, ptr %val.ptr, ptr %dst) { +define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigger.ptr, ptr %val.ptr, ptr %dst) nounwind { ; SSE2-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: ; SSE2: ## %bb.0: ; SSE2-NEXT: movdqa (%rdi), %xmm6 @@ -5874,23 +5873,11 @@ define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigge ; SSE4-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: ; SSE4: ## %bb.0: ; SSE4-NEXT: pushq %rbp -; SSE4-NEXT: .cfi_def_cfa_offset 16 ; SSE4-NEXT: pushq %r15 -; SSE4-NEXT: .cfi_def_cfa_offset 24 ; SSE4-NEXT: pushq %r14 -; SSE4-NEXT: .cfi_def_cfa_offset 32 ; SSE4-NEXT: pushq %r13 -; SSE4-NEXT: .cfi_def_cfa_offset 40 ; SSE4-NEXT: pushq %r12 -; SSE4-NEXT: .cfi_def_cfa_offset 48 ; SSE4-NEXT: pushq %rbx -; SSE4-NEXT: .cfi_def_cfa_offset 56 -; SSE4-NEXT: .cfi_offset %rbx, -56 -; SSE4-NEXT: .cfi_offset %r12, -48 -; SSE4-NEXT: .cfi_offset %r13, -40 -; SSE4-NEXT: .cfi_offset %r14, -32 -; SSE4-NEXT: .cfi_offset %r15, -24 -; SSE4-NEXT: .cfi_offset %rbp, -16 ; SSE4-NEXT: movdqa (%rdi), %xmm1 ; SSE4-NEXT: movdqa 32(%rdi), %xmm2 ; SSE4-NEXT: movdqa 64(%rdi), %xmm0 @@ -6266,7 +6253,7 @@ define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigge } ; From https://reviews.llvm.org/rGf8d9097168b7#1165311 -define void @undefshuffle(<8 x i1> %i0, ptr %src, ptr %dst) #0 { +define void @undefshuffle(<8 x i1> %i0, ptr %src, ptr %dst) nounwind { ; SSE2-LABEL: undefshuffle: ; SSE2: ## %bb.0: ## %else ; SSE2-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) -- GitLab From b8cc838427efa80eb5ca4ec7c8adb53e4adfc4c7 Mon Sep 17 00:00:00 2001 From: komalverma04 Date: Wed, 27 Mar 2024 05:51:27 -0700 Subject: [PATCH 054/541] [analyzer][docs] Document the `optin.performance.Padding` checker (#86411) Closes #73675 Co-authored-by: Balazs Benics Co-authored-by: NagyDonat --- clang/docs/analyzer/checkers.rst | 83 ++++++++++++++++++- .../clang/StaticAnalyzer/Checkers/Checkers.td | 2 +- 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index 66da1c7b35f2..8af99a021ebd 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -849,10 +849,89 @@ Check for performance anti-patterns when using Grand Central Dispatch. .. _optin-performance-Padding: -optin.performance.Padding -""""""""""""""""""""""""" +optin.performance.Padding (C, C++, ObjC) +"""""""""""""""""""""""""""""""""""""""" Check for excessively padded structs. +This checker detects structs with excessive padding, which can lead to wasted +memory thus decreased performance by reducing the effectiveness of the +processor cache. Padding bytes are added by compilers to align data accesses +as some processors require data to be aligned to certain boundaries. On others, +unaligned data access are possible, but impose significantly larger latencies. + +To avoid padding bytes, the fields of a struct should be ordered by decreasing +by alignment. Usually, its easier to think of the ``sizeof`` of the fields, and +ordering the fields by ``sizeof`` would usually also lead to the same optimal +layout. + +In rare cases, one can use the ``#pragma pack(1)`` directive to enforce a packed +layout too, but it can significantly increase the access times, so reordering the +fields is usually a better solution. + + +.. code-block:: cpp + + // warn: Excessive padding in 'struct NonOptimal' (35 padding bytes, where 3 is optimal) + struct NonOptimal { + char c1; + // 7 bytes of padding + std::int64_t big1; // 8 bytes + char c2; + // 7 bytes of padding + std::int64_t big2; // 8 bytes + char c3; + // 7 bytes of padding + std::int64_t big3; // 8 bytes + char c4; + // 7 bytes of padding + std::int64_t big4; // 8 bytes + char c5; + // 7 bytes of padding + }; + static_assert(sizeof(NonOptimal) == 4*8+5+5*7); + + // no-warning: The fields are nicely aligned to have the minimal amount of padding bytes. + struct Optimal { + std::int64_t big1; // 8 bytes + std::int64_t big2; // 8 bytes + std::int64_t big3; // 8 bytes + std::int64_t big4; // 8 bytes + char c1; + char c2; + char c3; + char c4; + char c5; + // 3 bytes of padding + }; + static_assert(sizeof(Optimal) == 4*8+5+3); + + // no-warning: Bit packing representation is also accepted by this checker, but + // it can significantly increase access times, so prefer reordering the fields. + #pragma pack(1) + struct BitPacked { + char c1; + std::int64_t big1; // 8 bytes + char c2; + std::int64_t big2; // 8 bytes + char c3; + std::int64_t big3; // 8 bytes + char c4; + std::int64_t big4; // 8 bytes + char c5; + }; + static_assert(sizeof(BitPacked) == 4*8+5); + +The ``AllowedPad`` option can be used to specify a threshold for the number +padding bytes raising the warning. If the number of padding bytes of the struct +and the optimal number of padding bytes differ by more than the threshold value, +a warning will be raised. + +By default, the ``AllowedPad`` threshold is 24 bytes. + +To override this threshold to e.g. 4 bytes, use the +``-analyzer-config optin.performance.Padding:AllowedPad=4`` option. + + .. _optin-portability-UnixAPI: optin.portability.UnixAPI diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index bf46766d44b3..5fe5c9286dab 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -908,7 +908,7 @@ def PaddingChecker : Checker<"Padding">, "24", Released> ]>, - Documentation; + Documentation; } // end: "padding" -- GitLab From 4f9aab2b500d3df0cc5d54f2d29c8199507af66c Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Wed, 27 Mar 2024 13:53:36 +0100 Subject: [PATCH 055/541] [NFC][TableGen][GlobalISel] Move MIR pattern parsing out of combiner (#86789) Reland of cfa0833ccc7450a322e709583e894e4c96ce682e --- llvm/utils/TableGen/Common/CMakeLists.txt | 2 + .../Common/GlobalISel/CombinerUtils.cpp | 23 + .../Common/GlobalISel/CombinerUtils.h | 4 + .../Common/GlobalISel/PatternParser.cpp | 462 +++++++++++++++++ .../Common/GlobalISel/PatternParser.h | 118 +++++ .../TableGen/GlobalISelCombinerEmitter.cpp | 479 +----------------- 6 files changed, 623 insertions(+), 465 deletions(-) create mode 100644 llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp create mode 100644 llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp create mode 100644 llvm/utils/TableGen/Common/GlobalISel/PatternParser.h diff --git a/llvm/utils/TableGen/Common/CMakeLists.txt b/llvm/utils/TableGen/Common/CMakeLists.txt index 0440f027f286..c31ed5a1de69 100644 --- a/llvm/utils/TableGen/Common/CMakeLists.txt +++ b/llvm/utils/TableGen/Common/CMakeLists.txt @@ -12,10 +12,12 @@ set(LLVM_LINK_COMPONENTS add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL GlobalISel/CodeExpander.cpp + GlobalISel/CombinerUtils.cpp GlobalISel/CXXPredicates.cpp GlobalISel/GlobalISelMatchTable.cpp GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp GlobalISel/MatchDataInfo.cpp + GlobalISel/PatternParser.cpp GlobalISel/Patterns.cpp AsmWriterInst.cpp diff --git a/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp new file mode 100644 index 000000000000..37e630605095 --- /dev/null +++ b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp @@ -0,0 +1,23 @@ +//===- CombinerUtils.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CombinerUtils.h" +#include "llvm/ADT/StringSet.h" + +namespace llvm { + +StringRef insertStrRef(StringRef S) { + if (S.empty()) + return {}; + + static StringSet<> Pool; + auto [It, Inserted] = Pool.insert(S); + return It->getKey(); +} + +} // namespace llvm diff --git a/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h index 8cb2514a10e8..82a64c63edbd 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h +++ b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h @@ -65,6 +65,10 @@ inline const DagInit *getDagWithOperatorOfSubClass(const Init &N, return I; return nullptr; } + +/// Copies a StringRef into a static pool to preserve it. +StringRef insertStrRef(StringRef S); + } // namespace llvm #endif diff --git a/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp new file mode 100644 index 000000000000..1d6c4c73a264 --- /dev/null +++ b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp @@ -0,0 +1,462 @@ +//===- PatternParser.cpp ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Common/GlobalISel/PatternParser.h" +#include "Basic/CodeGenIntrinsics.h" +#include "Common/CodeGenTarget.h" +#include "Common/GlobalISel/CombinerUtils.h" +#include "Common/GlobalISel/Patterns.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SaveAndRestore.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" + +namespace llvm { +namespace gi { +static constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum"; + +namespace { +class PrettyStackTraceParse : public PrettyStackTraceEntry { + const Record &Def; + +public: + PrettyStackTraceParse(const Record &Def) : Def(Def) {} + + void print(raw_ostream &OS) const override { + if (Def.isSubClassOf("GICombineRule")) + OS << "Parsing GICombineRule '" << Def.getName() << '\''; + else if (Def.isSubClassOf(PatFrag::ClassName)) + OS << "Parsing " << PatFrag::ClassName << " '" << Def.getName() << '\''; + else + OS << "Parsing '" << Def.getName() << '\''; + OS << '\n'; + } +}; +} // namespace + +bool PatternParser::parsePatternList( + const DagInit &List, + function_ref)> ParseAction, + StringRef Operator, StringRef AnonPatNamePrefix) { + if (List.getOperatorAsDef(DiagLoc)->getName() != Operator) { + PrintError(DiagLoc, "Expected " + Operator + " operator"); + return false; + } + + if (List.getNumArgs() == 0) { + PrintError(DiagLoc, Operator + " pattern list is empty"); + return false; + } + + // The match section consists of a list of matchers and predicates. Parse each + // one and add the equivalent GIMatchDag nodes, predicates, and edges. + for (unsigned I = 0; I < List.getNumArgs(); ++I) { + Init *Arg = List.getArg(I); + std::string Name = List.getArgName(I) + ? List.getArgName(I)->getValue().str() + : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str(); + + if (auto Pat = parseInstructionPattern(*Arg, Name)) { + if (!ParseAction(std::move(Pat))) + return false; + continue; + } + + if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) { + if (!ParseAction(std::move(Pat))) + return false; + continue; + } + + // Parse arbitrary C++ code + if (const auto *StringI = dyn_cast(Arg)) { + auto CXXPat = std::make_unique(*StringI, insertStrRef(Name)); + if (!ParseAction(std::move(CXXPat))) + return false; + continue; + } + + PrintError(DiagLoc, + "Failed to parse pattern: '" + Arg->getAsString() + '\''); + return false; + } + + return true; +} + +static const CodeGenInstruction & +getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) { + StringRef Opc; + if (I->isConvergent) { + Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS" + : "G_INTRINSIC_CONVERGENT"; + } else { + Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC"; + } + + RecordKeeper &RK = I->TheDef->getRecords(); + return CGT.getInstruction(RK.getDef(Opc)); +} + +static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) { + // Intrinsics need to have a static lifetime because the match table keeps + // references to CodeGenIntrinsic objects. + static DenseMap> + AllIntrinsics; + + auto &Ptr = AllIntrinsics[R]; + if (!Ptr) + Ptr = std::make_unique(R, std::vector()); + return Ptr.get(); +} + +std::unique_ptr +PatternParser::parseInstructionPattern(const Init &Arg, StringRef Name) { + const DagInit *DagPat = dyn_cast(&Arg); + if (!DagPat) + return nullptr; + + std::unique_ptr Pat; + if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) { + auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(DiagLoc)); + Pat = + std::make_unique(Instr, insertStrRef(Name)); + } else if (const DagInit *IP = + getDagWithOperatorOfSubClass(Arg, "Intrinsic")) { + Record *TheDef = IP->getOperatorAsDef(DiagLoc); + const CodeGenIntrinsic *Intrin = getCodeGenIntrinsic(TheDef); + const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin); + Pat = + std::make_unique(Instr, insertStrRef(Name)); + cast(*Pat).setIntrinsic(Intrin); + } else if (const DagInit *PFP = + getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) { + const Record *Def = PFP->getOperatorAsDef(DiagLoc); + const PatFrag *PF = parsePatFrag(Def); + if (!PF) + return nullptr; // Already diagnosed by parsePatFrag + Pat = std::make_unique(*PF, insertStrRef(Name)); + } else if (const DagInit *BP = + getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) { + Pat = std::make_unique(*BP->getOperatorAsDef(DiagLoc), + insertStrRef(Name)); + } else + return nullptr; + + for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) { + Init *Arg = DagPat->getArg(K); + if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) { + if (!parseInstructionPatternMIFlags(*Pat, DagArg)) + return nullptr; + continue; + } + + if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K))) + return nullptr; + } + + if (!Pat->checkSemantics(DiagLoc)) + return nullptr; + + return std::move(Pat); +} + +std::unique_ptr +PatternParser::parseWipMatchOpcodeMatcher(const Init &Arg, StringRef Name) { + const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode"); + if (!Matcher) + return nullptr; + + if (Matcher->getNumArgs() == 0) { + PrintError(DiagLoc, "Empty wip_match_opcode"); + return nullptr; + } + + // Each argument is an opcode that can match. + auto Result = std::make_unique(insertStrRef(Name)); + for (const auto &Arg : Matcher->getArgs()) { + Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction"); + if (OpcodeDef) { + Result->addOpcode(&CGT.getInstruction(OpcodeDef)); + continue; + } + + PrintError(DiagLoc, "Arguments to wip_match_opcode must be instructions"); + return nullptr; + } + + return std::move(Result); +} + +bool PatternParser::parseInstructionPatternOperand(InstructionPattern &IP, + const Init *OpInit, + const StringInit *OpName) { + const auto ParseErr = [&]() { + PrintError(DiagLoc, + "cannot parse operand '" + OpInit->getAsUnquotedString() + "' "); + if (OpName) + PrintNote(DiagLoc, + "operand name is '" + OpName->getAsUnquotedString() + '\''); + return false; + }; + + // untyped immediate, e.g. 0 + if (const auto *IntImm = dyn_cast(OpInit)) { + std::string Name = OpName ? OpName->getAsUnquotedString() : ""; + IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType()); + return true; + } + + // typed immediate, e.g. (i32 0) + if (const auto *DagOp = dyn_cast(OpInit)) { + if (DagOp->getNumArgs() != 1) + return ParseErr(); + + const Record *TyDef = DagOp->getOperatorAsDef(DiagLoc); + auto ImmTy = PatternType::get(DiagLoc, TyDef, + "cannot parse immediate '" + + DagOp->getAsUnquotedString() + '\''); + if (!ImmTy) + return false; + + if (!IP.hasAllDefs()) { + PrintError(DiagLoc, "out operand of '" + IP.getInstName() + + "' cannot be an immediate"); + return false; + } + + const auto *Val = dyn_cast(DagOp->getArg(0)); + if (!Val) + return ParseErr(); + + std::string Name = OpName ? OpName->getAsUnquotedString() : ""; + IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy); + return true; + } + + // Typed operand e.g. $x/$z in (G_FNEG $x, $z) + if (auto *DefI = dyn_cast(OpInit)) { + if (!OpName) { + PrintError(DiagLoc, "expected an operand name after '" + + OpInit->getAsString() + '\''); + return false; + } + const Record *Def = DefI->getDef(); + auto Ty = PatternType::get(DiagLoc, Def, "cannot parse operand type"); + if (!Ty) + return false; + IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty); + return true; + } + + // Untyped operand e.g. $x/$z in (G_FNEG $x, $z) + if (isa(OpInit)) { + assert(OpName && "Unset w/ no OpName?"); + IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType()); + return true; + } + + return ParseErr(); +} + +bool PatternParser::parseInstructionPatternMIFlags(InstructionPattern &IP, + const DagInit *Op) { + auto *CGIP = dyn_cast(&IP); + if (!CGIP) { + PrintError(DiagLoc, + "matching/writing MIFlags is only allowed on CodeGenInstruction " + "patterns"); + return false; + } + + const auto CheckFlagEnum = [&](const Record *R) { + if (!R->isSubClassOf(MIFlagsEnumClassName)) { + PrintError(DiagLoc, "'" + R->getName() + "' is not a subclass of '" + + MIFlagsEnumClassName + "'"); + return false; + } + + return true; + }; + + if (CGIP->getMIFlagsInfo()) { + PrintError(DiagLoc, "MIFlags can only be present once on an instruction"); + return false; + } + + auto &FI = CGIP->getOrCreateMIFlagsInfo(); + for (unsigned K = 0; K < Op->getNumArgs(); ++K) { + const Init *Arg = Op->getArg(K); + + // Match/set a flag: (MIFlags FmNoNans) + if (const auto *Def = dyn_cast(Arg)) { + const Record *R = Def->getDef(); + if (!CheckFlagEnum(R)) + return false; + + FI.addSetFlag(R); + continue; + } + + // Do not match a flag/unset a flag: (MIFlags (not FmNoNans)) + if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) { + for (const Init *NotArg : NotDag->getArgs()) { + const DefInit *DefArg = dyn_cast(NotArg); + if (!DefArg) { + PrintError(DiagLoc, "cannot parse '" + NotArg->getAsUnquotedString() + + "': expected a '" + MIFlagsEnumClassName + + "'"); + return false; + } + + const Record *R = DefArg->getDef(); + if (!CheckFlagEnum(R)) + return false; + + FI.addUnsetFlag(R); + continue; + } + + continue; + } + + // Copy flags from a matched instruction: (MIFlags $mi) + if (isa(Arg)) { + FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString())); + continue; + } + } + + return true; +} + +std::unique_ptr PatternParser::parsePatFragImpl(const Record *Def) { + auto StackTrace = PrettyStackTraceParse(*Def); + if (!Def->isSubClassOf(PatFrag::ClassName)) + return nullptr; + + const DagInit *Ins = Def->getValueAsDag("InOperands"); + if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") { + PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName + + " in operands list"); + return nullptr; + } + + const DagInit *Outs = Def->getValueAsDag("OutOperands"); + if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") { + PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName + + " out operands list"); + return nullptr; + } + + auto Result = std::make_unique(*Def); + if (!parsePatFragParamList(*Outs, [&](StringRef Name, unsigned Kind) { + Result->addOutParam(insertStrRef(Name), (PatFrag::ParamKind)Kind); + return true; + })) + return nullptr; + + if (!parsePatFragParamList(*Ins, [&](StringRef Name, unsigned Kind) { + Result->addInParam(insertStrRef(Name), (PatFrag::ParamKind)Kind); + return true; + })) + return nullptr; + + const ListInit *Alts = Def->getValueAsListInit("Alternatives"); + unsigned AltIdx = 0; + for (const Init *Alt : *Alts) { + const auto *PatDag = dyn_cast(Alt); + if (!PatDag) { + PrintError(Def, "expected dag init for PatFrag pattern alternative"); + return nullptr; + } + + PatFrag::Alternative &A = Result->addAlternative(); + const auto AddPat = [&](std::unique_ptr Pat) { + A.Pats.push_back(std::move(Pat)); + return true; + }; + + SaveAndRestore> DiagLocSAR(DiagLoc, Def->getLoc()); + if (!parsePatternList( + *PatDag, AddPat, "pattern", + /*AnonPatPrefix*/ + (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str())) + return nullptr; + } + + if (!Result->buildOperandsTables() || !Result->checkSemantics()) + return nullptr; + + return Result; +} + +bool PatternParser::parsePatFragParamList( + const DagInit &OpsList, + function_ref ParseAction) { + for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) { + const StringInit *Name = OpsList.getArgName(K); + const Init *Ty = OpsList.getArg(K); + + if (!Name) { + PrintError(DiagLoc, "all operands must be named'"); + return false; + } + const std::string NameStr = Name->getAsUnquotedString(); + + PatFrag::ParamKind OpKind; + if (isSpecificDef(*Ty, "gi_imm")) + OpKind = PatFrag::PK_Imm; + else if (isSpecificDef(*Ty, "root")) + OpKind = PatFrag::PK_Root; + else if (isa(Ty) || + isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo. + OpKind = PatFrag::PK_MachineOperand; + else { + PrintError( + DiagLoc, + '\'' + NameStr + + "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'"); + return false; + } + + if (!ParseAction(NameStr, (unsigned)OpKind)) + return false; + } + + return true; +} + +const PatFrag *PatternParser::parsePatFrag(const Record *Def) { + // Cache already parsed PatFrags to avoid doing extra work. + static DenseMap> ParsedPatFrags; + + auto It = ParsedPatFrags.find(Def); + if (It != ParsedPatFrags.end()) { + SeenPatFrags.insert(It->second.get()); + return It->second.get(); + } + + std::unique_ptr NewPatFrag = parsePatFragImpl(Def); + if (!NewPatFrag) { + PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" + + Def->getName() + "'"); + // Put a nullptr in the map so we don't attempt parsing this again. + ParsedPatFrags[Def] = nullptr; + return nullptr; + } + + const auto *Res = NewPatFrag.get(); + ParsedPatFrags[Def] = std::move(NewPatFrag); + SeenPatFrags.insert(Res); + return Res; +} + +} // namespace gi +} // namespace llvm diff --git a/llvm/utils/TableGen/Common/GlobalISel/PatternParser.h b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.h new file mode 100644 index 000000000000..cd6f524075cd --- /dev/null +++ b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.h @@ -0,0 +1,118 @@ +//===- PatternParser.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file Contains tools to parse MIR patterns from TableGen DAG elements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UTILS_GLOBALISEL_PATTERNPARSER_H +#define LLVM_UTILS_GLOBALISEL_PATTERNPARSER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/SMLoc.h" +#include + +namespace llvm { +class CodeGenTarget; +class DagInit; +class Init; +class Record; +class StringRef; +class StringInit; + +namespace gi { +class InstructionPattern; +class Pattern; +class PatFrag; + +/// Helper class to parse MIR Pattern lists. +/// +/// e.g., `(match (G_FADD $x, $y, $z), (G_FNEG $y, $z))` +class PatternParser { + const CodeGenTarget &CGT; + ArrayRef DiagLoc; + + mutable SmallPtrSet SeenPatFrags; + +public: + PatternParser(const CodeGenTarget &CGT, ArrayRef DiagLoc) + : CGT(CGT), DiagLoc(DiagLoc) {} + + /// Parses a list of patterns such as: + /// (Operator (Pattern1 ...), (Pattern2 ...)) + /// \param List DagInit of the expected pattern list. + /// \param ParseAction Callback to handle a succesfully parsed pattern. + /// \param Operator The name of the operator, e.g. "match" + /// \param AnonPatNamePrefix Prefix for anonymous pattern names. + /// \return true on success, false on failure. + bool + parsePatternList(const DagInit &List, + function_ref)> ParseAction, + StringRef Operator, StringRef AnonPatNamePrefix); + + /// \returns all PatFrags encountered by this PatternParser. + const auto &getSeenPatFrags() const { return SeenPatFrags; } + +private: + /// Parse any InstructionPattern from a TableGen Init. + /// \param Arg Init to parse. + /// \param PatName Name of the pattern that will be parsed. + /// \return the parsed pattern on success, nullptr on failure. + std::unique_ptr parseInstructionPattern(const Init &Arg, + StringRef PatName); + + /// Parse a WipOpcodeMatcher from a TableGen Init. + /// \param Arg Init to parse. + /// \param PatName Name of the pattern that will be parsed. + /// \return the parsed pattern on success, nullptr on failure. + std::unique_ptr parseWipMatchOpcodeMatcher(const Init &Arg, + StringRef PatName); + + /// Parses an Operand of an InstructionPattern from a TableGen Init. + /// \param IP InstructionPattern for which we're parsing. + /// \param OpInit Init to parse. + /// \param OpName Name of the operand to parse. + /// \return true on success, false on failure. + bool parseInstructionPatternOperand(InstructionPattern &IP, + const Init *OpInit, + const StringInit *OpName); + + /// Parses a MIFlag for an InstructionPattern from a TableGen Init. + /// \param IP InstructionPattern for which we're parsing. + /// \param Op Init to parse. + /// \return true on success, false on failure. + bool parseInstructionPatternMIFlags(InstructionPattern &IP, + const DagInit *Op); + + /// (Uncached) PatFrag parsing implementation. + /// \param Def PatFrag def to parsee. + /// \return the parsed PatFrag on success, nullptr on failure. + std::unique_ptr parsePatFragImpl(const Record *Def); + + /// Parses the in or out parameter list of a PatFrag. + /// \param OpsList Init to parse. + /// \param ParseAction Callback on successful parse, with the name of + /// the parameter and its \ref PatFrag::ParamKind + /// \return true on success, false on failure. + bool + parsePatFragParamList(const DagInit &OpsList, + function_ref ParseAction); + + /// Cached PatFrag parser. This avoids duplicate work by keeping track of + /// already-parsed PatFrags. + /// \param Def PatFrag def to parsee. + /// \return the parsed PatFrag on success, nullptr on failure. + const PatFrag *parsePatFrag(const Record *Def); +}; + +} // namespace gi +} // namespace llvm + +#endif diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index 39b9f8a2ae17..1ae6efd4a7d0 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -36,6 +36,7 @@ #include "Common/GlobalISel/GlobalISelMatchTable.h" #include "Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h" #include "Common/GlobalISel/MatchDataInfo.h" +#include "Common/GlobalISel/PatternParser.h" #include "Common/GlobalISel/Patterns.h" #include "Common/SubtargetFeatureInfo.h" #include "llvm/ADT/APInt.h" @@ -80,7 +81,6 @@ cl::opt DebugTypeInfer("gicombiner-debug-typeinfer", constexpr StringLiteral CXXApplyPrefix = "GICXXCustomAction_CombineApply"; constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_"; -constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum"; //===- CodeExpansions Helpers --------------------------------------------===// @@ -109,17 +109,6 @@ void declareTempRegExpansion(CodeExpansions &CE, unsigned TempRegID, //===- Misc. Helpers -----------------------------------------------------===// -/// Copies a StringRef into a static pool to preserve it. -/// Most Pattern classes use StringRef so we need this. -StringRef insertStrRef(StringRef S) { - if (S.empty()) - return {}; - - static StringSet<> Pool; - auto [It, Inserted] = Pool.insert(S); - return It->getKey(); -} - template auto keys(Container &&C) { return map_range(C, [](auto &Entry) -> auto & { return Entry.first; }); } @@ -639,8 +628,9 @@ public: SubtargetFeatureInfoMap &SubtargetFeatures, Record &RuleDef, unsigned ID, std::vector &OutRMs) - : CGT(CGT), SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef), - RuleID(ID), OutRMs(OutRMs) {} + : Parser(CGT, RuleDef.getLoc()), CGT(CGT), + SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef), RuleID(ID), + OutRMs(OutRMs) {} /// Parses all fields in the RuleDef record. bool parseAll(); @@ -718,26 +708,6 @@ private: bool buildRuleOperandsTable(); bool parseDefs(const DagInit &Def); - bool - parsePatternList(const DagInit &List, - function_ref)> ParseAction, - StringRef Operator, ArrayRef DiagLoc, - StringRef AnonPatNamePrefix) const; - - std::unique_ptr parseInstructionPattern(const Init &Arg, - StringRef PatName) const; - std::unique_ptr parseWipMatchOpcodeMatcher(const Init &Arg, - StringRef PatName) const; - bool parseInstructionPatternOperand(InstructionPattern &IP, - const Init *OpInit, - const StringInit *OpName) const; - bool parseInstructionPatternMIFlags(InstructionPattern &IP, - const DagInit *Op) const; - std::unique_ptr parsePatFragImpl(const Record *Def) const; - bool parsePatFragParamList( - ArrayRef DiagLoc, const DagInit &OpsList, - function_ref ParseAction) const; - const PatFrag *parsePatFrag(const Record *Def) const; bool emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts, const InstructionPattern &IP); @@ -781,6 +751,7 @@ private: DenseSet &SeenPats, OperandDefLookupFn LookupOperandDef, OperandMapperFnRef OperandMapper = [](const auto &O) { return O; }); + PatternParser Parser; const CodeGenTarget &CGT; SubtargetFeatureInfoMap &SubtargetFeatures; Record &RuleDef; @@ -808,9 +779,6 @@ private: SmallVector MatchDatas; SmallVector PermutationsToEmit; - - // print()/debug-only members. - mutable SmallPtrSet SeenPatFrags; }; bool CombineRuleBuilder::parseAll() { @@ -819,16 +787,16 @@ bool CombineRuleBuilder::parseAll() { if (!parseDefs(*RuleDef.getValueAsDag("Defs"))) return false; - if (!parsePatternList( + if (!Parser.parsePatternList( *RuleDef.getValueAsDag("Match"), [this](auto Pat) { return addMatchPattern(std::move(Pat)); }, "match", - RuleDef.getLoc(), (RuleDef.getName() + "_match").str())) + (RuleDef.getName() + "_match").str())) return false; - if (!parsePatternList( + if (!Parser.parsePatternList( *RuleDef.getValueAsDag("Apply"), [this](auto Pat) { return addApplyPattern(std::move(Pat)); }, "apply", - RuleDef.getLoc(), (RuleDef.getName() + "_apply").str())) + (RuleDef.getName() + "_apply").str())) return false; if (!buildRuleOperandsTable() || !typecheckPatterns() || !findRoots() || @@ -884,9 +852,10 @@ void CombineRuleBuilder::print(raw_ostream &OS) const { OS << " )\n"; } - if (!SeenPatFrags.empty()) { + const auto &SeenPFs = Parser.getSeenPatFrags(); + if (!SeenPFs.empty()) { OS << " (PatFrags\n"; - for (const auto *PF : SeenPatFrags) { + for (const auto *PF : Parser.getSeenPatFrags()) { PF->print(OS, /*Indent=*/" "); OS << '\n'; } @@ -1500,426 +1469,6 @@ bool CombineRuleBuilder::parseDefs(const DagInit &Def) { return true; } -bool CombineRuleBuilder::parsePatternList( - const DagInit &List, - function_ref)> ParseAction, - StringRef Operator, ArrayRef DiagLoc, - StringRef AnonPatNamePrefix) const { - if (List.getOperatorAsDef(RuleDef.getLoc())->getName() != Operator) { - ::PrintError(DiagLoc, "Expected " + Operator + " operator"); - return false; - } - - if (List.getNumArgs() == 0) { - ::PrintError(DiagLoc, Operator + " pattern list is empty"); - return false; - } - - // The match section consists of a list of matchers and predicates. Parse each - // one and add the equivalent GIMatchDag nodes, predicates, and edges. - for (unsigned I = 0; I < List.getNumArgs(); ++I) { - Init *Arg = List.getArg(I); - std::string Name = List.getArgName(I) - ? List.getArgName(I)->getValue().str() - : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str(); - - if (auto Pat = parseInstructionPattern(*Arg, Name)) { - if (!ParseAction(std::move(Pat))) - return false; - continue; - } - - if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) { - if (!ParseAction(std::move(Pat))) - return false; - continue; - } - - // Parse arbitrary C++ code - if (const auto *StringI = dyn_cast(Arg)) { - auto CXXPat = std::make_unique(*StringI, insertStrRef(Name)); - if (!ParseAction(std::move(CXXPat))) - return false; - continue; - } - - ::PrintError(DiagLoc, - "Failed to parse pattern: '" + Arg->getAsString() + "'"); - return false; - } - - return true; -} - -static const CodeGenInstruction & -getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) { - StringRef Opc; - if (I->isConvergent) { - Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS" - : "G_INTRINSIC_CONVERGENT"; - } else { - Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC"; - } - - RecordKeeper &RK = I->TheDef->getRecords(); - return CGT.getInstruction(RK.getDef(Opc)); -} - -static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) { - // Intrinsics need to have a static lifetime because the match table keeps - // references to CodeGenIntrinsic objects. - static DenseMap> - AllIntrinsics; - - auto &Ptr = AllIntrinsics[R]; - if (!Ptr) - Ptr = std::make_unique(R, std::vector()); - return Ptr.get(); -} - -std::unique_ptr -CombineRuleBuilder::parseInstructionPattern(const Init &Arg, - StringRef Name) const { - const DagInit *DagPat = dyn_cast(&Arg); - if (!DagPat) - return nullptr; - - std::unique_ptr Pat; - if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) { - auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(RuleDef.getLoc())); - Pat = - std::make_unique(Instr, insertStrRef(Name)); - } else if (const DagInit *IP = - getDagWithOperatorOfSubClass(Arg, "Intrinsic")) { - Record *TheDef = IP->getOperatorAsDef(RuleDef.getLoc()); - const CodeGenIntrinsic *Intrin = getCodeGenIntrinsic(TheDef); - const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin); - Pat = - std::make_unique(Instr, insertStrRef(Name)); - cast(*Pat).setIntrinsic(Intrin); - } else if (const DagInit *PFP = - getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) { - const Record *Def = PFP->getOperatorAsDef(RuleDef.getLoc()); - const PatFrag *PF = parsePatFrag(Def); - if (!PF) - return nullptr; // Already diagnosed by parsePatFrag - Pat = std::make_unique(*PF, insertStrRef(Name)); - } else if (const DagInit *BP = - getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) { - Pat = std::make_unique( - *BP->getOperatorAsDef(RuleDef.getLoc()), insertStrRef(Name)); - } else - return nullptr; - - for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) { - Init *Arg = DagPat->getArg(K); - if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) { - if (!parseInstructionPatternMIFlags(*Pat, DagArg)) - return nullptr; - continue; - } - - if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K))) - return nullptr; - } - - if (!Pat->checkSemantics(RuleDef.getLoc())) - return nullptr; - - return std::move(Pat); -} - -std::unique_ptr -CombineRuleBuilder::parseWipMatchOpcodeMatcher(const Init &Arg, - StringRef Name) const { - const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode"); - if (!Matcher) - return nullptr; - - if (Matcher->getNumArgs() == 0) { - PrintError("Empty wip_match_opcode"); - return nullptr; - } - - // Each argument is an opcode that can match. - auto Result = std::make_unique(insertStrRef(Name)); - for (const auto &Arg : Matcher->getArgs()) { - Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction"); - if (OpcodeDef) { - Result->addOpcode(&CGT.getInstruction(OpcodeDef)); - continue; - } - - PrintError("Arguments to wip_match_opcode must be instructions"); - return nullptr; - } - - return std::move(Result); -} - -bool CombineRuleBuilder::parseInstructionPatternOperand( - InstructionPattern &IP, const Init *OpInit, - const StringInit *OpName) const { - const auto ParseErr = [&]() { - PrintError("cannot parse operand '" + OpInit->getAsUnquotedString() + "' "); - if (OpName) - PrintNote("operand name is '" + OpName->getAsUnquotedString() + "'"); - return false; - }; - - // untyped immediate, e.g. 0 - if (const auto *IntImm = dyn_cast(OpInit)) { - std::string Name = OpName ? OpName->getAsUnquotedString() : ""; - IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType()); - return true; - } - - // typed immediate, e.g. (i32 0) - if (const auto *DagOp = dyn_cast(OpInit)) { - if (DagOp->getNumArgs() != 1) - return ParseErr(); - - const Record *TyDef = DagOp->getOperatorAsDef(RuleDef.getLoc()); - auto ImmTy = PatternType::get(RuleDef.getLoc(), TyDef, - "cannot parse immediate '" + - DagOp->getAsUnquotedString() + "'"); - if (!ImmTy) - return false; - - if (!IP.hasAllDefs()) { - PrintError("out operand of '" + IP.getInstName() + - "' cannot be an immediate"); - return false; - } - - const auto *Val = dyn_cast(DagOp->getArg(0)); - if (!Val) - return ParseErr(); - - std::string Name = OpName ? OpName->getAsUnquotedString() : ""; - IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy); - return true; - } - - // Typed operand e.g. $x/$z in (G_FNEG $x, $z) - if (auto *DefI = dyn_cast(OpInit)) { - if (!OpName) { - PrintError("expected an operand name after '" + OpInit->getAsString() + - "'"); - return false; - } - const Record *Def = DefI->getDef(); - auto Ty = - PatternType::get(RuleDef.getLoc(), Def, "cannot parse operand type"); - if (!Ty) - return false; - IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty); - return true; - } - - // Untyped operand e.g. $x/$z in (G_FNEG $x, $z) - if (isa(OpInit)) { - assert(OpName && "Unset w/ no OpName?"); - IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType()); - return true; - } - - return ParseErr(); -} - -bool CombineRuleBuilder::parseInstructionPatternMIFlags( - InstructionPattern &IP, const DagInit *Op) const { - auto *CGIP = dyn_cast(&IP); - if (!CGIP) { - PrintError("matching/writing MIFlags is only allowed on CodeGenInstruction " - "patterns"); - return false; - } - - const auto CheckFlagEnum = [&](const Record *R) { - if (!R->isSubClassOf(MIFlagsEnumClassName)) { - PrintError("'" + R->getName() + "' is not a subclass of '" + - MIFlagsEnumClassName + "'"); - return false; - } - - return true; - }; - - if (CGIP->getMIFlagsInfo()) { - PrintError("MIFlags can only be present once on an instruction"); - return false; - } - - auto &FI = CGIP->getOrCreateMIFlagsInfo(); - for (unsigned K = 0; K < Op->getNumArgs(); ++K) { - const Init *Arg = Op->getArg(K); - - // Match/set a flag: (MIFlags FmNoNans) - if (const auto *Def = dyn_cast(Arg)) { - const Record *R = Def->getDef(); - if (!CheckFlagEnum(R)) - return false; - - FI.addSetFlag(R); - continue; - } - - // Do not match a flag/unset a flag: (MIFlags (not FmNoNans)) - if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) { - for (const Init *NotArg : NotDag->getArgs()) { - const DefInit *DefArg = dyn_cast(NotArg); - if (!DefArg) { - PrintError("cannot parse '" + NotArg->getAsUnquotedString() + - "': expected a '" + MIFlagsEnumClassName + "'"); - return false; - } - - const Record *R = DefArg->getDef(); - if (!CheckFlagEnum(R)) - return false; - - FI.addUnsetFlag(R); - continue; - } - - continue; - } - - // Copy flags from a matched instruction: (MIFlags $mi) - if (isa(Arg)) { - FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString())); - continue; - } - } - - return true; -} - -std::unique_ptr -CombineRuleBuilder::parsePatFragImpl(const Record *Def) const { - auto StackTrace = PrettyStackTraceParse(*Def); - if (!Def->isSubClassOf(PatFrag::ClassName)) - return nullptr; - - const DagInit *Ins = Def->getValueAsDag("InOperands"); - if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") { - ::PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName + - " in operands list"); - return nullptr; - } - - const DagInit *Outs = Def->getValueAsDag("OutOperands"); - if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") { - ::PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName + - " out operands list"); - return nullptr; - } - - auto Result = std::make_unique(*Def); - if (!parsePatFragParamList(Def->getLoc(), *Outs, - [&](StringRef Name, PatFrag::ParamKind Kind) { - Result->addOutParam(insertStrRef(Name), Kind); - return true; - })) - return nullptr; - - if (!parsePatFragParamList(Def->getLoc(), *Ins, - [&](StringRef Name, PatFrag::ParamKind Kind) { - Result->addInParam(insertStrRef(Name), Kind); - return true; - })) - return nullptr; - - const ListInit *Alts = Def->getValueAsListInit("Alternatives"); - unsigned AltIdx = 0; - for (const Init *Alt : *Alts) { - const auto *PatDag = dyn_cast(Alt); - if (!PatDag) { - ::PrintError(Def, "expected dag init for PatFrag pattern alternative"); - return nullptr; - } - - PatFrag::Alternative &A = Result->addAlternative(); - const auto AddPat = [&](std::unique_ptr Pat) { - A.Pats.push_back(std::move(Pat)); - return true; - }; - - if (!parsePatternList( - *PatDag, AddPat, "pattern", Def->getLoc(), - /*AnonPatPrefix*/ - (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str())) - return nullptr; - } - - if (!Result->buildOperandsTables() || !Result->checkSemantics()) - return nullptr; - - return Result; -} - -bool CombineRuleBuilder::parsePatFragParamList( - ArrayRef DiagLoc, const DagInit &OpsList, - function_ref ParseAction) const { - for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) { - const StringInit *Name = OpsList.getArgName(K); - const Init *Ty = OpsList.getArg(K); - - if (!Name) { - ::PrintError(DiagLoc, "all operands must be named'"); - return false; - } - const std::string NameStr = Name->getAsUnquotedString(); - - PatFrag::ParamKind OpKind; - if (isSpecificDef(*Ty, "gi_imm")) - OpKind = PatFrag::PK_Imm; - else if (isSpecificDef(*Ty, "root")) - OpKind = PatFrag::PK_Root; - else if (isa(Ty) || - isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo. - OpKind = PatFrag::PK_MachineOperand; - else { - ::PrintError( - DiagLoc, - "'" + NameStr + - "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'"); - return false; - } - - if (!ParseAction(NameStr, OpKind)) - return false; - } - - return true; -} - -const PatFrag *CombineRuleBuilder::parsePatFrag(const Record *Def) const { - // Cache already parsed PatFrags to avoid doing extra work. - static DenseMap> ParsedPatFrags; - - auto It = ParsedPatFrags.find(Def); - if (It != ParsedPatFrags.end()) { - SeenPatFrags.insert(It->second.get()); - return It->second.get(); - } - - std::unique_ptr NewPatFrag = parsePatFragImpl(Def); - if (!NewPatFrag) { - ::PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" + - Def->getName() + "'"); - // Put a nullptr in the map so we don't attempt parsing this again. - ParsedPatFrags[Def] = nullptr; - return nullptr; - } - - const auto *Res = NewPatFrag.get(); - ParsedPatFrags[Def] = std::move(NewPatFrag); - SeenPatFrags.insert(Res); - return Res; -} - bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts, const InstructionPattern &IP) { @@ -2956,8 +2505,8 @@ GICombinerEmitter::buildMatchTable(MutableArrayRef Rules) { const Matcher *B) { auto *L = static_cast(A); auto *R = static_cast(B); - return std::tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) < - std::tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands()); + return std::make_tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) < + std::make_tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands()); }); for (Matcher *Rule : InputRules) -- GitLab From 26464f2662d13c7c6ef9f8180b1653c046cd60a7 Mon Sep 17 00:00:00 2001 From: Justin Cady Date: Wed, 27 Mar 2024 09:03:46 -0400 Subject: [PATCH 056/541] [FreeBSD] Mark __stack_chk_guard dso_local except for PPC64 (#86665) Adjust logic of 1cb9f37a17ab to match freebsd/freebsd-src@9a4d48a645a7a. D113443 is the original attempt to bring this FreeBSD patch to llvm-project, but it never landed. This change is required to build FreeBSD kernel modules with -fstack-protector using a standard LLVM toolchain. The FreeBSD kernel loader does not handle R_X86_64_REX_GOTPCRELX relocations. Fixes #50932. --- llvm/lib/CodeGen/TargetLoweringBase.cpp | 3 ++- llvm/test/CodeGen/X86/stack-protector.ll | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 9990556f89ed..b16e78daf586 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -2073,7 +2073,8 @@ void TargetLoweringBase::insertSSPDeclarations(Module &M) const { // FreeBSD has "__stack_chk_guard" defined externally on libc.so if (M.getDirectAccessExternalData() && !TM.getTargetTriple().isWindowsGNUEnvironment() && - !TM.getTargetTriple().isOSFreeBSD() && + !(TM.getTargetTriple().isPPC64() && + TM.getTargetTriple().isOSFreeBSD()) && (!TM.getTargetTriple().isOSDarwin() || TM.getRelocationModel() == Reloc::Static)) GV->setDSOLocal(true); diff --git a/llvm/test/CodeGen/X86/stack-protector.ll b/llvm/test/CodeGen/X86/stack-protector.ll index a277f9f862ab..f4f3ae4f55f2 100644 --- a/llvm/test/CodeGen/X86/stack-protector.ll +++ b/llvm/test/CodeGen/X86/stack-protector.ll @@ -1,6 +1,7 @@ ; RUN: llc -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-I386 %s ; RUN: llc -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-X64 %s ; RUN: llc -code-model=kernel -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-KERNEL-X64 %s +; RUN: llc -code-model=kernel -mtriple=x86_64-unknown-freebsd < %s -o - | FileCheck --check-prefix=FREEBSD-KERNEL-X64 %s ; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | FileCheck --check-prefix=DARWIN-X64 %s ; RUN: llc -mtriple=amd64-pc-openbsd < %s -o - | FileCheck --check-prefix=OPENBSD-AMD64 %s ; RUN: llc -mtriple=i386-pc-windows-msvc < %s -o - | FileCheck -check-prefix=MSVC-I386 %s @@ -75,6 +76,10 @@ entry: ; LINUX-X64: mov{{l|q}} %fs: ; LINUX-X64: callq __stack_chk_fail +; FREEBSD-KERNEL-X64-LABEL: test1b: +; FREEBSD-KERNEL-X64-NOT: mov{{l|q}} __stack_chk_guard@GOTPCREL +; FREEBSD-KERNEL-X64: callq __stack_chk_fail + ; LINUX-KERNEL-X64-LABEL: test1b: ; LINUX-KERNEL-X64: mov{{l|q}} %gs: ; LINUX-KERNEL-X64: callq __stack_chk_fail @@ -118,6 +123,10 @@ entry: ; LINUX-X64: mov{{l|q}} %fs: ; LINUX-X64: callq __stack_chk_fail +; FREEBSD-KERNEL-X64-LABEL: test1c: +; FREEBSD-KERNEL-X64: mov{{l|q}} __stack_chk_guard(%rip) +; FREEBSD-KERNEL-X64: callq __stack_chk_fail + ; LINUX-KERNEL-X64-LABEL: test1c: ; LINUX-KERNEL-X64: mov{{l|q}} %gs: ; LINUX-KERNEL-X64: callq __stack_chk_fail -- GitLab From 932949dbb517b089af28fdc480a16a738ee5db78 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Wed, 27 Mar 2024 13:13:06 +0000 Subject: [PATCH 057/541] [APINotes] Upstream the remaining API Notes fixes and tests This upstreams the last bits of Clang API Notes functionality that is currently implemented in the Apple fork: https://github.com/apple/llvm-project/tree/next/clang/lib/APINotes --- clang/lib/Sema/SemaAPINotes.cpp | 41 ++-- clang/lib/Sema/SemaObjCProperty.cpp | 4 +- .../Inputs/APINotes/SomeOtherKit.apinotes | 8 + .../Inputs/BrokenHeaders/APINotes.apinotes | 5 + .../Inputs/BrokenHeaders/SomeBrokenLib.h | 6 + .../Inputs/BrokenHeaders2/APINotes.apinotes | 7 + .../Inputs/BrokenHeaders2/SomeBrokenLib.h | 6 + .../FrameworkWithActualPrivateModule.h | 1 + .../Modules/module.modulemap | 5 + .../Modules/module.private.modulemap | 5 + ...rkWithActualPrivateModule_Private.apinotes | 1 + ...FrameworkWithActualPrivateModule_Private.h | 2 + .../Headers/FrameworkWithWrongCase.h | 1 + .../Modules/module.modulemap | 5 + .../FrameworkWithWrongCase_Private.apinotes | 1 + .../Headers/FrameworkWithWrongCasePrivate.h | 1 + .../Modules/module.modulemap | 5 + .../Modules/module.private.modulemap | 1 + ...eworkWithWrongCasePrivate_Private.apinotes | 1 + .../LayeredKit.framework/Headers/LayeredKit.h | 11 ++ .../Modules/module.modulemap | 5 + .../Headers/LayeredKitImpl.apinotes | 9 + .../Headers/LayeredKitImpl.h | 7 + .../Modules/module.modulemap | 5 + .../Modules/module.modulemap | 5 + .../APINotes/SomeKit.apinotes | 74 +++++++ .../APINotes/SomeKit_private.apinotes | 15 ++ .../Headers/SomeKitForNullAnnotation.h | 55 ++++++ .../Modules/module.modulemap | 5 + .../Modules/module.private.modulemap | 8 + .../Modules/module_private.modulemap | 8 + .../PrivateHeaders/SomeKit_Private.h | 16 ++ .../SomeKit_PrivateForNullAnnotation.h | 17 ++ .../PrivateHeaders/SomeKit_private.apinotes | 15 ++ .../APINotes/SomeOtherKit.apinotes | 8 + .../Headers/SomeOtherKit.apinotes | 8 + .../Headers/SomeOtherKit.h | 9 + .../Modules/module.modulemap | 5 + .../Headers/TopLevelPrivateKit.h | 1 + .../TopLevelPrivateKit_Private.apinotes | 1 + .../Modules/module.modulemap | 5 + .../Modules/module.private.modulemap | 5 + .../TopLevelPrivateKit.apinotes | 1 + .../TopLevelPrivateKit_Private.apinotes | 4 + .../TopLevelPrivateKit_Private.h | 1 + ...opLevelPrivateKit_Private_private.apinotes | 1 + .../Headers/VersionedKit.apinotes | 156 +++++++++++++++ .../Headers/VersionedKit.h | 137 +++++++++++++ .../Modules/module.modulemap | 5 + .../APINotes/Inputs/Headers/APINotes.apinotes | 18 ++ .../Inputs/Headers/BrokenTypes.apinotes | 10 + .../APINotes/Inputs/Headers/BrokenTypes.h | 8 + .../Inputs/Headers/ExternCtx.apinotes | 15 ++ .../test/APINotes/Inputs/Headers/ExternCtx.h | 11 ++ .../Inputs/Headers/HeaderLib.apinotes | 37 ++++ .../test/APINotes/Inputs/Headers/HeaderLib.h | 19 ++ .../Headers/InstancetypeModule.apinotes | 10 + .../Inputs/Headers/InstancetypeModule.h | 10 + .../Inputs/Headers/ModuleWithWrongCase.h | 1 + .../Headers/ModuleWithWrongCasePrivate.h | 1 + ...oduleWithWrongCasePrivate_Private.apinotes | 1 + .../ModuleWithWrongCase_Private.apinotes | 1 + .../Inputs/Headers/Namespaces.apinotes | 53 +++++ .../test/APINotes/Inputs/Headers/Namespaces.h | 39 ++++ .../Inputs/Headers/PrivateLib.apinotes | 4 + .../test/APINotes/Inputs/Headers/PrivateLib.h | 1 + .../Headers/PrivateLib_private.apinotes | 1 + .../Inputs/Headers/SwiftImportAs.apinotes | 9 + .../APINotes/Inputs/Headers/SwiftImportAs.h | 6 + .../APINotes/Inputs/Headers/module.modulemap | 31 +++ .../Inputs/Headers/module.private.modulemap | 5 + .../Inputs/yaml-reader-errors/UIKit.apinotes | 65 ++++++ .../Inputs/yaml-reader-errors/UIKit.h | 1 + .../yaml-reader-errors/module.modulemap | 3 + clang/test/APINotes/availability.m | 48 +++++ clang/test/APINotes/broken_types.m | 19 ++ .../APINotes/case-for-private-apinotes-file.c | 22 +++ clang/test/APINotes/extern-context.cpp | 23 +++ clang/test/APINotes/instancetype.m | 9 + clang/test/APINotes/module-cache.m | 65 ++++++ clang/test/APINotes/namespaces.cpp | 69 +++++++ clang/test/APINotes/nullability.c | 21 ++ clang/test/APINotes/nullability.m | 46 +++++ .../test/APINotes/objc-forward-declarations.m | 12 ++ clang/test/APINotes/objc_designated_inits.m | 17 ++ clang/test/APINotes/properties.m | 42 ++++ clang/test/APINotes/retain-count-convention.m | 38 ++++ clang/test/APINotes/search-order.m | 25 +++ clang/test/APINotes/swift-import-as.cpp | 16 ++ .../test/APINotes/top-level-private-modules.c | 8 + clang/test/APINotes/types.m | 28 +++ clang/test/APINotes/versioned-multi.c | 69 +++++++ clang/test/APINotes/versioned.m | 187 ++++++++++++++++++ clang/test/APINotes/yaml-convert-diags.c | 6 + clang/test/APINotes/yaml-parse-diags.c | 6 + clang/test/APINotes/yaml-reader-errors.m | 5 + 96 files changed, 1829 insertions(+), 20 deletions(-) create mode 100644 clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes create mode 100644 clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes create mode 100644 clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h create mode 100644 clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes create mode 100644 clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes create mode 100644 clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h create mode 100644 clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Headers/APINotes.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/BrokenTypes.h create mode 100644 clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/ExternCtx.h create mode 100644 clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/HeaderLib.h create mode 100644 clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/InstancetypeModule.h create mode 100644 clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h create mode 100644 clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h create mode 100644 clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Namespaces.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/Namespaces.h create mode 100644 clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/PrivateLib.h create mode 100644 clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/SwiftImportAs.h create mode 100644 clang/test/APINotes/Inputs/Headers/module.modulemap create mode 100644 clang/test/APINotes/Inputs/Headers/module.private.modulemap create mode 100644 clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes create mode 100644 clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h create mode 100644 clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap create mode 100644 clang/test/APINotes/availability.m create mode 100644 clang/test/APINotes/broken_types.m create mode 100644 clang/test/APINotes/case-for-private-apinotes-file.c create mode 100644 clang/test/APINotes/extern-context.cpp create mode 100644 clang/test/APINotes/instancetype.m create mode 100644 clang/test/APINotes/module-cache.m create mode 100644 clang/test/APINotes/namespaces.cpp create mode 100644 clang/test/APINotes/nullability.c create mode 100644 clang/test/APINotes/nullability.m create mode 100644 clang/test/APINotes/objc-forward-declarations.m create mode 100644 clang/test/APINotes/objc_designated_inits.m create mode 100644 clang/test/APINotes/properties.m create mode 100644 clang/test/APINotes/retain-count-convention.m create mode 100644 clang/test/APINotes/search-order.m create mode 100644 clang/test/APINotes/swift-import-as.cpp create mode 100644 clang/test/APINotes/top-level-private-modules.c create mode 100644 clang/test/APINotes/types.m create mode 100644 clang/test/APINotes/versioned-multi.c create mode 100644 clang/test/APINotes/versioned.m create mode 100644 clang/test/APINotes/yaml-convert-diags.c create mode 100644 clang/test/APINotes/yaml-parse-diags.c create mode 100644 clang/test/APINotes/yaml-reader-errors.m diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 836c633e9d20..a3128306c664 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -52,49 +52,54 @@ static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, if (!Metadata.IsActive) return; - auto IsModified = [&](Decl *D, QualType QT, - NullabilityKind Nullability) -> bool { + auto GetModified = + [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> std::optional { QualType Original = QT; S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), isa(D), /*OverrideExisting=*/true); - return QT.getTypePtr() != Original.getTypePtr(); + return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT) + : std::nullopt; }; if (auto Function = dyn_cast(D)) { - if (IsModified(D, Function->getReturnType(), Nullability)) { - QualType FnType = Function->getType(); - Function->setType(FnType); + if (auto Modified = + GetModified(D, Function->getReturnType(), Nullability)) { + const FunctionType *FnType = Function->getType()->castAs(); + if (const FunctionProtoType *proto = dyn_cast(FnType)) + Function->setType(S.Context.getFunctionType( + *Modified, proto->getParamTypes(), proto->getExtProtoInfo())); + else + Function->setType( + S.Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo())); } } else if (auto Method = dyn_cast(D)) { - QualType Type = Method->getReturnType(); - if (IsModified(D, Type, Nullability)) { - Method->setReturnType(Type); + if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) { + Method->setReturnType(*Modified); // Make it a context-sensitive keyword if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } else if (auto Value = dyn_cast(D)) { - QualType Type = Value->getType(); - if (IsModified(D, Type, Nullability)) { - Value->setType(Type); + if (auto Modified = GetModified(D, Value->getType(), Nullability)) { + Value->setType(*Modified); // Make it a context-sensitive keyword if we can. if (auto Parm = dyn_cast(D)) { - if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) + if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified)) Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } } else if (auto Property = dyn_cast(D)) { - QualType Type = Property->getType(); - if (IsModified(D, Type, Nullability)) { - Property->setType(Type, Property->getTypeSourceInfo()); + if (auto Modified = GetModified(D, Property->getType(), Nullability)) { + Property->setType(*Modified, Property->getTypeSourceInfo()); // Make it a property attribute if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Property->setPropertyAttributes( ObjCPropertyAttribute::kind_null_resettable); } diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 4636d89ebf2b..f9e1ad0121e2 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -638,8 +638,6 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setInvalidDecl(); } - ProcessDeclAttributes(S, PDecl, FD.D); - // Regardless of setter/getter attribute, we save the default getter/setter // selector names in anticipation of declaration of setter/getter methods. PDecl->setGetterName(GetterSel, GetterNameLoc); @@ -647,6 +645,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setPropertyAttributesAsWritten( makePropertyAttributesAsWritten(AttributesAsWritten)); + ProcessDeclAttributes(S, PDecl, FD.D); + if (Attributes & ObjCPropertyAttribute::kind_readonly) PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); diff --git a/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes new file mode 100644 index 000000000000..ccdc4e15d34d --- /dev/null +++ b/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodB" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes b/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes new file mode 100644 index 000000000000..cd5475b13423 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes @@ -0,0 +1,5 @@ +Name: SomeBrokenLib +Functions: + - Name: do_something_with_pointers + Nu llabilityOfRet: O + # the space is intentional, to make sure we don't crash on malformed API Notes diff --git a/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h b/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h new file mode 100644 index 000000000000..b09c6f63eae0 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h @@ -0,0 +1,6 @@ +#ifndef SOME_BROKEN_LIB_H +#define SOME_BROKEN_LIB_H + +void do_something_with_pointers(int *ptr1, int *ptr2); + +#endif // SOME_BROKEN_LIB_H diff --git a/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes b/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes new file mode 100644 index 000000000000..33eeaaada999 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes @@ -0,0 +1,7 @@ +Name: SomeBrokenLib +Functions: + - Name: do_something_with_pointers + NullabilityOfRet: O + - Name: do_something_with_pointers + NullabilityOfRet: O + diff --git a/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h b/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h new file mode 100644 index 000000000000..b09c6f63eae0 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h @@ -0,0 +1,6 @@ +#ifndef SOME_BROKEN_LIB_H +#define SOME_BROKEN_LIB_H + +void do_something_with_pointers(int *ptr1, int *ptr2); + +#endif // SOME_BROKEN_LIB_H diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h new file mode 100644 index 000000000000..523de4f7ce08 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h @@ -0,0 +1 @@ +extern int FrameworkWithActualPrivateModule; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap new file mode 100644 index 000000000000..859d723716be --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithActualPrivateModule { + umbrella header "FrameworkWithActualPrivateModule.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap new file mode 100644 index 000000000000..e7fafe3bcbb1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithActualPrivateModule_Private { + umbrella header "FrameworkWithActualPrivateModule_Private.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes new file mode 100644 index 000000000000..831cf1e93d35 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithActualPrivateModule_Private diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h new file mode 100644 index 000000000000..c07a3e95d740 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h @@ -0,0 +1,2 @@ +#include +extern int FrameworkWithActualPrivateModule_Private; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h new file mode 100644 index 000000000000..4f3b631c27e3 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h @@ -0,0 +1 @@ +extern int FrameworkWithWrongCase; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap new file mode 100644 index 000000000000..e97d361039a1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithWrongCase { + umbrella header "FrameworkWithWrongCase.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes new file mode 100644 index 000000000000..ae5447c61e33 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithWrongCase diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h new file mode 100644 index 000000000000..d3d61483191c --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h @@ -0,0 +1 @@ +extern int FrameworkWithWrongCasePrivate; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap new file mode 100644 index 000000000000..04b96adbbfeb --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithWrongCasePrivate { + umbrella header "FrameworkWithWrongCasePrivate.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap new file mode 100644 index 000000000000..d6ad53cdc717 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap @@ -0,0 +1 @@ +module FrameworkWithWrongCasePrivate.Inner {} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes new file mode 100644 index 000000000000..d7af293e8125 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h new file mode 100644 index 000000000000..a95d19ecbe9a --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h @@ -0,0 +1,11 @@ +@import LayeredKitImpl; + +// @interface declarations already don't inherit attributes from forward +// declarations, so in order to test this properly we have to /not/ define +// UpwardClass anywhere. + +// @interface UpwardClass +// @end + +@protocol UpwardProto +@end diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap new file mode 100644 index 000000000000..04bbe72a2b6e --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module LayeredKit { + umbrella header "LayeredKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes new file mode 100644 index 000000000000..bece28cfe605 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes @@ -0,0 +1,9 @@ +Name: LayeredKitImpl +Classes: +- Name: PerfectlyNormalClass + Availability: none +- Name: UpwardClass + Availability: none +Protocols: +- Name: UpwardProto + Availability: none diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h new file mode 100644 index 000000000000..99591d35803a --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h @@ -0,0 +1,7 @@ +@protocol UpwardProto; +@class UpwardClass; + +@interface PerfectlyNormalClass +@end + +void doImplementationThings(UpwardClass *first, id second) __attribute((unavailable)); diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap new file mode 100644 index 000000000000..58a6e55c1067 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module LayeredKitImpl { + umbrella header "LayeredKitImpl.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap new file mode 100644 index 000000000000..2d07e76c0a14 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SimpleKit { + umbrella header "SimpleKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes new file mode 100644 index 000000000000..817af123fc77 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes @@ -0,0 +1,74 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "transform:" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" + - Selector: "transform:integer:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: intValue + PropertyKind: Instance + Availability: none + AvailabilityMsg: "wouldn't work anyway" + - Name: nonnullAInstance + PropertyKind: Instance + Nullability: N + - Name: nonnullAClass + PropertyKind: Class + Nullability: N + - Name: nonnullABoth + Nullability: N + - Name: B + Availability: none + AvailabilityMsg: "just don't" + - Name: C + Methods: + - Selector: "initWithA:" + MethodKind: Instance + DesignatedInit: true + - Name: OverriddenTypes + Methods: + - Selector: "methodToMangle:second:" + MethodKind: Instance + ResultType: 'char *' + Parameters: + - Position: 0 + Type: 'SOMEKIT_DOUBLE *' + - Position: 1 + Type: 'float *' + Properties: + - Name: intPropertyToMangle + PropertyKind: Instance + Type: 'double *' +Functions: + - Name: global_int_fun + ResultType: 'char *' + Parameters: + - Position: 0 + Type: 'double *' + - Position: 1 + Type: 'float *' +Globals: + - Name: global_int_ptr + Type: 'double *' +SwiftVersions: + - Version: 3.0 + Classes: + - Name: A + Methods: + - Selector: "transform:integer:" + MethodKind: Instance + NullabilityOfRet: O + Nullability: [ O, S ] + Properties: + - Name: explicitNonnullInstance + PropertyKind: Instance + Nullability: O + - Name: explicitNullableInstance + PropertyKind: Instance + Nullability: N diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes new file mode 100644 index 000000000000..28ede9dfa25c --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes @@ -0,0 +1,15 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "privateTransform:input:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: internalProperty + Nullability: N +Protocols: + - Name: InternalProtocol + Availability: none + AvailabilityMsg: "not for you" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h new file mode 100644 index 000000000000..bc0c5da8848e --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h @@ -0,0 +1,55 @@ +#ifndef SOMEKIT_H +#define SOMEKIT_H + +#define ROOT_CLASS __attribute__((objc_root_class)) + +ROOT_CLASS +@interface A +-(A*)transform:(A*)input; +-(A*)transform:(A*)input integer:(int)integer; + +@property (nonatomic, readonly, retain) A* someA; +@property (nonatomic, retain) A* someOtherA; + +@property (nonatomic) int intValue; +@end + +@interface B : A +@end + +@interface C : A +- (instancetype)init; +- (instancetype)initWithA:(A*)a; +@end + + +@interface MyClass : A +- Inst; ++ Clas; +@end + +struct CGRect { + float origin; + float size; +}; +typedef struct CGRect NSRect; + +@interface I +- (void) Meth : (NSRect[4])exposedRects; +- (void) Meth1 : (const I*)exposedRects; +- (void) Meth2 : (const I*)exposedRects; +- (void) Meth3 : (I*)exposedRects; +- (const I*) Meth4; +- (const I*) Meth5 : (int) Arg1 : (const I*)Arg2 : (double)Arg3 : (const I*) Arg4 :(const volatile id) Arg5; +- (volatile const I*) Meth6 : (const char *)Arg1 : (const char *)Arg2 : (double)Arg3 : (const I*) Arg4 :(const volatile id) Arg5; +@end + +@class NSURL, NSArray, NSError; +@interface INTF_BLOCKS + + (void)getNonLocalVersionsOfItemAtURL:(NSURL *)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (void *)getNonLocalVersionsOfItemAtURL2:(NSURL *)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (NSError **)getNonLocalVersionsOfItemAtURL3:(int)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (id)getNonLocalVersionsOfItemAtURL4:(NSURL *)url completionHandler:(void (^)(int nonLocalFileVersions, NSError *error, NSURL*))completionHandler; +@end + +#endif diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap new file mode 100644 index 000000000000..3abee2df0be1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SomeKit { + umbrella header "SomeKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap new file mode 100644 index 000000000000..bbda9d08e399 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap @@ -0,0 +1,8 @@ +module SomeKit.Private { + header "SomeKit_Private.h" + export * + + explicit module NullAnnotation { + header "SomeKit_PrivateForNullAnnotation.h" + } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap new file mode 100644 index 000000000000..e31034317cb8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap @@ -0,0 +1,8 @@ +explicit framework module SomeKit.Private { + header "SomeKit_Private.h" + explicit NullAnnotation { header "SomeKit_PrivateForNullAnnotation.h" } + export * + module * { export * } +syntax error + +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h new file mode 100644 index 000000000000..c7611123e4ad --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h @@ -0,0 +1,16 @@ +#ifndef SOMEKIT_PRIVATE_H +#define SOMEKIT_PRIVATE_H + +#import + +@interface A(Private) +-(A*)privateTransform:(A*)input; + +@property (nonatomic) A* internalProperty; +@end + +@protocol InternalProtocol +@end + +#endif + diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h new file mode 100644 index 000000000000..bae4456b4080 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h @@ -0,0 +1,17 @@ +#ifndef SOMEKIT_PRIVATE_H +#define SOMEKIT_PRIVATE_H + +#import + +@interface A(Private) +-(A*)privateTransform:(A*)input; + +@property (nonatomic) A* internalProperty; +@end + +@protocol InternalProtocol +- (id) MomeMethod; +@end + +#endif + diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes new file mode 100644 index 000000000000..28ede9dfa25c --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes @@ -0,0 +1,15 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "privateTransform:input:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: internalProperty + Nullability: N +Protocols: + - Name: InternalProtocol + Availability: none + AvailabilityMsg: "not for you" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes new file mode 100644 index 000000000000..2ad546b8f8bc --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodA" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes new file mode 100644 index 000000000000..2ad546b8f8bc --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodA" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h new file mode 100644 index 000000000000..3911d765230c --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h @@ -0,0 +1,9 @@ +#ifndef SOME_OTHER_KIT_H + +__attribute__((objc_root_class)) +@interface A +-(void)methodA; +-(void)methodB; +@end + +#endif diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap new file mode 100644 index 000000000000..0aaad92e041c --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SomeOtherKit { + umbrella header "SomeOtherKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h new file mode 100644 index 000000000000..d3376f1dac5d --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h @@ -0,0 +1 @@ +extern int TopLevelPrivateKit_Public; diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes new file mode 100644 index 000000000000..ece1dd220adf --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read \ No newline at end of file diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap new file mode 100644 index 000000000000..70faa54e8347 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module TopLevelPrivateKit { + umbrella header "TopLevelPrivateKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap new file mode 100644 index 000000000000..0958a14d6710 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap @@ -0,0 +1,5 @@ +framework module TopLevelPrivateKit_Private { + umbrella header "TopLevelPrivateKit_Private.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes new file mode 100644 index 000000000000..908dae0e3b0b --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes new file mode 100644 index 000000000000..43323621588b --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes @@ -0,0 +1,4 @@ +Name: TopLevelPrivateKit_Private +Globals: +- Name: TopLevelPrivateKit_Private + Type: float diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h new file mode 100644 index 000000000000..39cbfe6e9918 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h @@ -0,0 +1 @@ +extern int TopLevelPrivateKit_Private; diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes new file mode 100644 index 000000000000..ece1dd220adf --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read \ No newline at end of file diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes new file mode 100644 index 000000000000..572c714b3d61 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes @@ -0,0 +1,156 @@ +Name: VersionedKit +Classes: + - Name: TestProperties + SwiftObjCMembers: true + Properties: + - Name: accessorsOnly + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClass + PropertyKind: Class + SwiftImportAsAccessors: true + - Name: accessorsOnlyExceptInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClassExceptInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: true +Functions: + - Name: unversionedRenameDUMP + SwiftName: 'unversionedRename_NOTES()' +Tags: + - Name: APINotedFlagEnum + FlagEnum: true + - Name: APINotedOpenEnum + EnumExtensibility: open + - Name: APINotedClosedEnum + EnumExtensibility: closed + - Name: SoonToBeCFEnum + EnumKind: CFEnum + - Name: SoonToBeNSEnum + EnumKind: NSEnum + - Name: SoonToBeCFOptions + EnumKind: CFOptions + - Name: SoonToBeNSOptions + EnumKind: NSOptions + - Name: SoonToBeCFClosedEnum + EnumKind: CFClosedEnum + - Name: SoonToBeNSClosedEnum + EnumKind: NSClosedEnum + - Name: UndoAllThatHasBeenDoneToMe + EnumKind: none +Typedefs: + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_NEW + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_NEW + - Name: MultiVersionedTypedef4Notes + SwiftName: MultiVersionedTypedef4Notes_NEW + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_NEW +SwiftVersions: + - Version: 3.0 + Classes: + - Name: MyReferenceType + SwiftBridge: '' + - Name: TestGenericDUMP + SwiftImportAsNonGeneric: true + - Name: TestProperties + SwiftObjCMembers: false + Properties: + - Name: accessorsOnlyInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClassInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: true + - Name: accessorsOnlyExceptInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: false + - Name: accessorsOnlyForClassExceptInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: false + - Name: Swift3RenamedOnlyDUMP + SwiftName: SpecialSwift3Name + - Name: Swift3RenamedAlsoDUMP + SwiftName: SpecialSwift3Also + Functions: + - Name: moveToPointDUMP + SwiftName: 'moveTo(a:b:)' + - Name: acceptClosure + Parameters: + - Position: 0 + NoEscape: false + - Name: privateFunc + SwiftPrivate: false + Tags: + - Name: MyErrorCode + NSErrorDomain: '' + - Name: NewlyFlagEnum + FlagEnum: false + - Name: OpenToClosedEnum + EnumExtensibility: open + - Name: ClosedToOpenEnum + EnumExtensibility: closed + - Name: NewlyClosedEnum + EnumExtensibility: none + - Name: NewlyOpenEnum + EnumExtensibility: none + Typedefs: + - Name: MyDoubleWrapper + SwiftWrapper: none + - Name: MultiVersionedTypedef34 + SwiftName: MultiVersionedTypedef34_3 + - Name: MultiVersionedTypedef34Header + SwiftName: MultiVersionedTypedef34Header_3 + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_3 + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_3 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_3 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_3 + - Version: 5 + Typedefs: + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_5 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_5 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_5 + - Name: MultiVersionedTypedef45 + SwiftName: MultiVersionedTypedef45_5 + - Name: MultiVersionedTypedef45Header + SwiftName: MultiVersionedTypedef45Header_5 + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_5 + - Version: 4 # Versions are deliberately ordered as "3, 5, 4" to catch bugs. + Classes: + - Name: Swift4RenamedDUMP + SwiftName: SpecialSwift4Name + Typedefs: + - Name: MultiVersionedTypedef34 + SwiftName: MultiVersionedTypedef34_4 + - Name: MultiVersionedTypedef34Header + SwiftName: MultiVersionedTypedef34Header_4 + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_4 + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_4 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_4 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_4 + - Name: MultiVersionedTypedef4 + SwiftName: MultiVersionedTypedef4_4 + - Name: MultiVersionedTypedef4Header + SwiftName: MultiVersionedTypedef4Header_4 + - Name: MultiVersionedTypedef4Notes + SwiftName: MultiVersionedTypedef4Notes_4 + - Name: MultiVersionedTypedef45 + SwiftName: MultiVersionedTypedef45_4 + - Name: MultiVersionedTypedef45Header + SwiftName: MultiVersionedTypedef45Header_4 + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_4 diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h new file mode 100644 index 000000000000..9ce95633c523 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h @@ -0,0 +1,137 @@ +void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)"))); + +void unversionedRenameDUMP(void) __attribute__((swift_name("unversionedRename_HEADER()"))); + +void acceptClosure(void (^ __attribute__((noescape)) block)(void)); + +void privateFunc(void) __attribute__((swift_private)); + +typedef double MyDoubleWrapper __attribute__((swift_wrapper(struct))); + +#if __OBJC__ +@class NSString; + +extern NSString *MyErrorDomain; + +enum __attribute__((ns_error_domain(MyErrorDomain))) MyErrorCode { + MyErrorCodeFailed = 1 +}; + +__attribute__((swift_bridge("MyValueType"))) +@interface MyReferenceType +@end + +@interface TestProperties +@property (nonatomic, readwrite, retain) id accessorsOnly; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClass; + +@property (nonatomic, readwrite, retain) id accessorsOnlyInVersion3; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClassInVersion3; + +@property (nonatomic, readwrite, retain) id accessorsOnlyExceptInVersion3; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClassExceptInVersion3; +@end + +@interface Base +@end + +@interface TestGenericDUMP : Base +- (Element)element; +@end + +@interface Swift3RenamedOnlyDUMP +@end + +__attribute__((swift_name("Swift4Name"))) +@interface Swift3RenamedAlsoDUMP +@end + +@interface Swift4RenamedDUMP +@end + +#endif + + +enum __attribute__((flag_enum)) FlagEnum { + FlagEnumA = 1, + FlagEnumB = 2 +}; + +enum __attribute__((flag_enum)) NewlyFlagEnum { + NewlyFlagEnumA = 1, + NewlyFlagEnumB = 2 +}; + +enum APINotedFlagEnum { + APINotedFlagEnumA = 1, + APINotedFlagEnumB = 2 +}; + + +enum __attribute__((enum_extensibility(open))) OpenEnum { + OpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(open))) NewlyOpenEnum { + NewlyOpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(closed))) NewlyClosedEnum { + NewlyClosedEnumA = 1, +}; + +enum __attribute__((enum_extensibility(open))) ClosedToOpenEnum { + ClosedToOpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(closed))) OpenToClosedEnum { + OpenToClosedEnumA = 1, +}; + +enum APINotedOpenEnum { + APINotedOpenEnumA = 1, +}; + +enum APINotedClosedEnum { + APINotedClosedEnumA = 1, +}; + + +enum SoonToBeCFEnum { + SoonToBeCFEnumA = 1 +}; +enum SoonToBeNSEnum { + SoonToBeNSEnumA = 1 +}; +enum SoonToBeCFOptions { + SoonToBeCFOptionsA = 1 +}; +enum SoonToBeNSOptions { + SoonToBeNSOptionsA = 1 +}; +enum SoonToBeCFClosedEnum { + SoonToBeCFClosedEnumA = 1 +}; +enum SoonToBeNSClosedEnum { + SoonToBeNSClosedEnumA = 1 +}; +enum UndoAllThatHasBeenDoneToMe { + UndoAllThatHasBeenDoneToMeA = 1 +} __attribute__((flag_enum)) __attribute__((enum_extensibility(closed))); + + +typedef int MultiVersionedTypedef4; +typedef int MultiVersionedTypedef4Notes; +typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); + +typedef int MultiVersionedTypedef34; +typedef int MultiVersionedTypedef34Notes; +typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); + +typedef int MultiVersionedTypedef45; +typedef int MultiVersionedTypedef45Notes; +typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_NEW"))); + +typedef int MultiVersionedTypedef345; +typedef int MultiVersionedTypedef345Notes; +typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_NEW"))); diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap new file mode 100644 index 000000000000..6d957fd68009 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module VersionedKit { + umbrella header "VersionedKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Headers/APINotes.apinotes b/clang/test/APINotes/Inputs/Headers/APINotes.apinotes new file mode 100644 index 000000000000..08210fc70565 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/APINotes.apinotes @@ -0,0 +1,18 @@ +Name: HeaderLib +SwiftInferImportAsMember: true +Functions: + - Name: custom_realloc + NullabilityOfRet: N + Nullability: [ N, S ] + - Name: unavailable_function + Availability: none + AvailabilityMsg: "I beg you not to use this" + - Name: do_something_with_pointers + NullabilityOfRet: O + Nullability: [ N, O ] + +Globals: + - Name: global_int + Nullability: N + - Name: unavailable_global_int + Availability: none diff --git a/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes b/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes new file mode 100644 index 000000000000..00f7b5074e98 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes @@ -0,0 +1,10 @@ +Name: BrokenTypes +Functions: + - Name: break_me_function + ResultType: 'int * with extra junk' + Parameters: + - Position: 0 + Type: 'not_a_type' +Globals: + - Name: break_me_variable + Type: 'double' diff --git a/clang/test/APINotes/Inputs/Headers/BrokenTypes.h b/clang/test/APINotes/Inputs/Headers/BrokenTypes.h new file mode 100644 index 000000000000..fee054b74cf7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/BrokenTypes.h @@ -0,0 +1,8 @@ +#ifndef BROKEN_TYPES_H +#define BROKEN_TYPES_H + +char break_me_function(void *ptr); + +extern char break_me_variable; + +#endif // BROKEN_TYPES_H diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes new file mode 100644 index 000000000000..0f47ac6deea8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes @@ -0,0 +1,15 @@ +Name: ExternCtx +Globals: + - Name: globalInExternC + Availability: none + AvailabilityMsg: "oh no" + - Name: globalInExternCXX + Availability: none + AvailabilityMsg: "oh no #2" +Functions: + - Name: globalFuncInExternC + Availability: none + AvailabilityMsg: "oh no #3" + - Name: globalFuncInExternCXX + Availability: none + AvailabilityMsg: "oh no #4" diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.h b/clang/test/APINotes/Inputs/Headers/ExternCtx.h new file mode 100644 index 000000000000..669d443f60ec --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.h @@ -0,0 +1,11 @@ +extern "C" { + static int globalInExternC = 1; + + static void globalFuncInExternC() {} +} + +extern "C++" { + static int globalInExternCXX = 2; + + static void globalFuncInExternCXX() {} +} diff --git a/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes b/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes new file mode 100644 index 000000000000..7dcb22476a1d --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes @@ -0,0 +1,37 @@ +Name: HeaderLib +SwiftInferImportAsMember: true +Functions: + - Name: custom_realloc + NullabilityOfRet: N + Nullability: [ N, S ] + - Name: unavailable_function + Availability: none + AvailabilityMsg: "I beg you not to use this" + - Name: do_something_with_pointers + NullabilityOfRet: O + Nullability: [ N, O ] + - Name: do_something_with_arrays + Parameters: + - Position: 0 + Nullability: N + - Position: 1 + Nullability: N + - Name: take_pointer_and_int + Parameters: + - Position: 0 + Nullability: N + NoEscape: true + - Position: 1 + NoEscape: true +Globals: + - Name: global_int + Nullability: N + - Name: unavailable_global_int + Availability: none +Tags: + - Name: unavailable_struct + Availability: none + +Typedefs: + - Name: unavailable_typedef + Availability: none diff --git a/clang/test/APINotes/Inputs/Headers/HeaderLib.h b/clang/test/APINotes/Inputs/Headers/HeaderLib.h new file mode 100644 index 000000000000..806524960785 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/HeaderLib.h @@ -0,0 +1,19 @@ +#ifndef HEADER_LIB_H +#define HEADER_LIB_H + +void *custom_realloc(void *member, unsigned size); + +int *global_int; + +int unavailable_function(void); +int unavailable_global_int; + +void do_something_with_pointers(int *ptr1, int *ptr2); +void do_something_with_arrays(int simple[], int nested[][2]); + +typedef int unavailable_typedef; +struct unavailable_struct { int x, y, z; }; + +void take_pointer_and_int(int *ptr1, int value); + +#endif diff --git a/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes new file mode 100644 index 000000000000..813eb506f39a --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes @@ -0,0 +1,10 @@ +Name: InstancetypeModule +Classes: +- Name: SomeBaseClass + Methods: + - Selector: instancetypeFactoryMethod + MethodKind: Class + ResultType: SomeBaseClass * _Nonnull + - Selector: staticFactoryMethod + MethodKind: Class + ResultType: SomeBaseClass * _Nonnull diff --git a/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h new file mode 100644 index 000000000000..767f201d9faf --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h @@ -0,0 +1,10 @@ +@interface Object +@end + +@interface SomeBaseClass : Object ++ (nullable instancetype)instancetypeFactoryMethod; ++ (nullable SomeBaseClass *)staticFactoryMethod; +@end + +@interface SomeSubclass : SomeBaseClass +@end diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h new file mode 100644 index 000000000000..867a15cae9a6 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h @@ -0,0 +1 @@ +extern int ModuleWithWrongCase; diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h new file mode 100644 index 000000000000..aa014296ca7d --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h @@ -0,0 +1 @@ +extern int ModuleWithWrongCasePrivate; diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes new file mode 100644 index 000000000000..dc6dc50bab6e --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes @@ -0,0 +1 @@ +Name: ModuleWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes new file mode 100644 index 000000000000..dc6dc50bab6e --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes @@ -0,0 +1 @@ +Name: ModuleWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes new file mode 100644 index 000000000000..e9da36787b63 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes @@ -0,0 +1,53 @@ +--- +Name: Namespaces +Globals: + - Name: varInInlineNamespace + SwiftName: swiftVarInInlineNamespace +Functions: + - Name: funcInNamespace + SwiftName: inWrongContext() + - Name: funcInInlineNamespace + SwiftName: swiftFuncInInlineNamespace() +Tags: + - Name: char_box + SwiftName: InWrongContext +Namespaces: + - Name: Namespace1 + Typedefs: + - Name: my_typedef + SwiftName: SwiftTypedef + - Name: my_using_decl + SwiftName: SwiftUsingDecl + Globals: + - Name: varInNamespace + SwiftName: swiftVarInNamespace + Functions: + - Name: funcInNamespace + SwiftName: swiftFuncInNamespace() + Tags: + - Name: char_box + SwiftName: CharBox + Namespaces: + - Name: Nested1 + Globals: + - Name: varInNestedNamespace + SwiftName: swiftVarInNestedNamespace + Functions: + - Name: funcInNestedNamespace + SwiftName: swiftFuncInNestedNamespace(_:) + Tags: + - Name: char_box + SwiftName: NestedCharBox + Namespaces: + - Name: Namespace1 + Tags: + - Name: char_box + SwiftName: DeepNestedCharBox + - Name: Nested2 + Globals: + - Name: varInNestedNamespace + SwiftName: swiftAnotherVarInNestedNamespace + - Name: InlineNamespace1 + Functions: + - Name: funcInInlineNamespace + SwiftName: shouldNotSpellOutInlineNamespaces() diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.h b/clang/test/APINotes/Inputs/Headers/Namespaces.h new file mode 100644 index 000000000000..6a79e996be86 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.h @@ -0,0 +1,39 @@ +namespace Namespace1 { namespace Nested1 {} } + +namespace Namespace1 { +static int varInNamespace = 1; +struct char_box { char c; }; +void funcInNamespace(); + +namespace Nested1 { +void funcInNestedNamespace(int i); +struct char_box { + char c; +}; +} + +namespace Nested1 { +static int varInNestedNamespace = 1; +void funcInNestedNamespace(int i); + +namespace Namespace1 { +struct char_box { char c; }; +} // namespace Namespace1 +} // namespace Nested1 + +namespace Nested2 { +static int varInNestedNamespace = 2; +} // namespace Nested2 + +namespace Nested1 { namespace Namespace1 {} } +} // namespace Namespace1 + +namespace Namespace1 { +typedef int my_typedef; +using my_using_decl = int; +} + +inline namespace InlineNamespace1 { +static int varInInlineNamespace = 3; +void funcInInlineNamespace(); +} diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes b/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes new file mode 100644 index 000000000000..5f62284aadca --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes @@ -0,0 +1,4 @@ +Name: HeaderLib +Globals: +- Name: PrivateLib + Type: float diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib.h b/clang/test/APINotes/Inputs/Headers/PrivateLib.h new file mode 100644 index 000000000000..59aeef09bdd3 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib.h @@ -0,0 +1 @@ +extern int PrivateLib; diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes b/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes new file mode 100644 index 000000000000..908dae0e3b0b --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes new file mode 100644 index 000000000000..5dbb83cab86b --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes @@ -0,0 +1,9 @@ +--- +Name: SwiftImportAs +Tags: +- Name: ImmortalRefType + SwiftImportAs: reference +- Name: RefCountedType + SwiftImportAs: reference + SwiftReleaseOp: RCRelease + SwiftRetainOp: RCRetain diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h new file mode 100644 index 000000000000..82b8a6749c4f --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h @@ -0,0 +1,6 @@ +struct ImmortalRefType {}; + +struct RefCountedType { int value; }; + +inline void RCRetain(RefCountedType *x) { x->value++; } +inline void RCRelease(RefCountedType *x) { x->value--; } diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap new file mode 100644 index 000000000000..98b4ee3e96cf --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -0,0 +1,31 @@ +module ExternCtx { + header "ExternCtx.h" +} + +module HeaderLib { + header "HeaderLib.h" +} + +module InstancetypeModule { + header "InstancetypeModule.h" +} + +module BrokenTypes { + header "BrokenTypes.h" +} + +module ModuleWithWrongCase { + header "ModuleWithWrongCase.h" +} + +module ModuleWithWrongCasePrivate { + header "ModuleWithWrongCasePrivate.h" +} + +module Namespaces { + header "Namespaces.h" +} + +module SwiftImportAs { + header "SwiftImportAs.h" +} diff --git a/clang/test/APINotes/Inputs/Headers/module.private.modulemap b/clang/test/APINotes/Inputs/Headers/module.private.modulemap new file mode 100644 index 000000000000..2ecf322ed18d --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/module.private.modulemap @@ -0,0 +1,5 @@ +module PrivateLib { + header "PrivateLib.h" +} + +module ModuleWithWrongCasePrivate.Inner {} diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes new file mode 100644 index 000000000000..77db84400899 --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes @@ -0,0 +1,65 @@ +--- +Name: UIKit +Classes: + - Name: UIFont + Methods: + - Selector: 'fontWithName:size:' + MethodKind: Instance + Nullability: [ N ] + NullabilityOfRet: O + DesignatedInit: true +# CHECK: duplicate definition of method '-[UIFont fontWithName:size:]' + - Selector: 'fontWithName:size:' + MethodKind: Instance + Nullability: [ N ] + NullabilityOfRet: O + DesignatedInit: true + Properties: + - Name: familyName + Nullability: N + - Name: fontName + Nullability: N +# CHECK: duplicate definition of instance property 'UIFont.familyName' + - Name: familyName + Nullability: N +# CHECK: multiple definitions of class 'UIFont' + - Name: UIFont +Protocols: + - Name: MyProto + AuditedForNullability: true +# CHECK: multiple definitions of protocol 'MyProto' + - Name: MyProto + AuditedForNullability: true +Functions: + - Name: 'globalFoo' + Nullability: [ N, N, O, S ] + NullabilityOfRet: O + - Name: 'globalFoo2' + Nullability: [ N, N, O, S ] + NullabilityOfRet: O +Globals: + - Name: globalVar + Nullability: O + - Name: globalVar2 + Nullability: O +Tags: +# CHECK: cannot mix EnumKind and FlagEnum (for FlagAndEnumKind) + - Name: FlagAndEnumKind + FlagEnum: true + EnumKind: CFOptions +# CHECK: cannot mix EnumKind and FlagEnum (for FlagAndEnumKind2) + - Name: FlagAndEnumKind2 + EnumKind: CFOptions + FlagEnum: false +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind) + - Name: ExtensibilityAndEnumKind + EnumExtensibility: open + EnumKind: CFOptions +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind2) + - Name: ExtensibilityAndEnumKind2 + EnumKind: CFOptions + EnumExtensibility: closed +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind3) + - Name: ExtensibilityAndEnumKind3 + EnumKind: none + EnumExtensibility: none diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h new file mode 100644 index 000000000000..55313ae260ae --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h @@ -0,0 +1 @@ +extern int yesOfCourseThisIsWhatUIKitLooksLike; diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap b/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap new file mode 100644 index 000000000000..3d683d705cac --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap @@ -0,0 +1,3 @@ +module UIKit { + header "UIKit.h" +} diff --git a/clang/test/APINotes/availability.m b/clang/test/APINotes/availability.m new file mode 100644 index 000000000000..2ddc2a73da80 --- /dev/null +++ b/clang/test/APINotes/availability.m @@ -0,0 +1,48 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -Wno-private-module -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" +#import +#import + +int main() { + int i; + i = unavailable_function(); // expected-error{{'unavailable_function' is unavailable: I beg you not to use this}} + // expected-note@HeaderLib.h:8{{'unavailable_function' has been explicitly marked unavailable here}} + i = unavailable_global_int; // expected-error{{'unavailable_global_int' is unavailable}} + // expected-note@HeaderLib.h:9{{'unavailable_global_int' has been explicitly marked unavailable here}} + + unavailable_typedef t; // expected-error{{'unavailable_typedef' is unavailable}} + // expected-note@HeaderLib.h:14{{'unavailable_typedef' has been explicitly marked unavailable here}} + + struct unavailable_struct s; // expected-error{{'unavailable_struct' is unavailable}} + // expected-note@HeaderLib.h:15{{'unavailable_struct' has been explicitly marked unavailable here}} + + B *b = 0; // expected-error{{'B' is unavailable: just don't}} + // expected-note@SomeKit/SomeKit.h:15{{'B' has been explicitly marked unavailable here}} + + id proto = 0; // expected-error{{'InternalProtocol' is unavailable: not for you}} + // expected-note@SomeKit/SomeKit_Private.h:12{{'InternalProtocol' has been explicitly marked unavailable here}} + + A *a = 0; + i = a.intValue; // expected-error{{intValue' is unavailable: wouldn't work anyway}} + // expected-note@SomeKit/SomeKit.h:12{{'intValue' has been explicitly marked unavailable here}} + + [a transform:a]; // expected-error{{'transform:' is unavailable: anything but this}} + // expected-note@SomeKit/SomeKit.h:6{{'transform:' has been explicitly marked unavailable here}} + + [a implicitGetOnlyInstance]; // expected-error{{'implicitGetOnlyInstance' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:53{{'implicitGetOnlyInstance' has been explicitly marked unavailable here}} + [A implicitGetOnlyClass]; // expected-error{{'implicitGetOnlyClass' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:54{{'implicitGetOnlyClass' has been explicitly marked unavailable here}} + [a implicitGetSetInstance]; // expected-error{{'implicitGetSetInstance' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:56{{'implicitGetSetInstance' has been explicitly marked unavailable here}} + [a setImplicitGetSetInstance: a]; // expected-error{{'setImplicitGetSetInstance:' is unavailable: setter gone}} + // expected-note@SomeKit/SomeKit.h:56{{'setImplicitGetSetInstance:' has been explicitly marked unavailable here}} + [A implicitGetSetClass]; // expected-error{{'implicitGetSetClass' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:57{{'implicitGetSetClass' has been explicitly marked unavailable here}} + [A setImplicitGetSetClass: a]; // expected-error{{'setImplicitGetSetClass:' is unavailable: setter gone}} + // expected-note@SomeKit/SomeKit.h:57{{'setImplicitGetSetClass:' has been explicitly marked unavailable here}} + return 0; +} + diff --git a/clang/test/APINotes/broken_types.m b/clang/test/APINotes/broken_types.m new file mode 100644 index 000000000000..ee33ff7c4b4b --- /dev/null +++ b/clang/test/APINotes/broken_types.m @@ -0,0 +1,19 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s 2> %t.err +// RUN: FileCheck %s < %t.err + +#include "BrokenTypes.h" + +// CHECK: :1:1: error: unknown type name 'not_a_type' +// CHECK-NEXT: not_a_type +// CHECK-NEXT: ^ + +// CHECK: :1:7: error: unparsed tokens following type +// CHECK-NEXT: int * with extra junk +// CHECK-NEXT: ^ + +// CHECK: BrokenTypes.h:4:6: error: API notes replacement type 'int *' has a different size from original type 'char' + +// CHECK: BrokenTypes.h:6:13: error: API notes replacement type 'double' has a different size from original type 'char' + +// CHECK: 5 errors generated. diff --git a/clang/test/APINotes/case-for-private-apinotes-file.c b/clang/test/APINotes/case-for-private-apinotes-file.c new file mode 100644 index 000000000000..6aff3db54918 --- /dev/null +++ b/clang/test/APINotes/case-for-private-apinotes-file.c @@ -0,0 +1,22 @@ +// REQUIRES: case-insensitive-filesystem + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/Frameworks -I %S/Inputs/Headers %s 2>&1 | FileCheck %s + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -iframework %S/Inputs/Frameworks -isystem %S/Inputs/Headers %s -Werror + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -iframework %S/Inputs/Frameworks -isystem %S/Inputs/Headers %s -Wnonportable-private-system-apinotes-path 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include + +// CHECK-NOT: warning: +// CHECK: warning: private API notes file for module 'ModuleWithWrongCasePrivate' should be named 'ModuleWithWrongCasePrivate_private.apinotes', not 'ModuleWithWrongCasePrivate_Private.apinotes' +// CHECK-NOT: warning: +// CHECK: warning: private API notes file for module 'FrameworkWithWrongCasePrivate' should be named 'FrameworkWithWrongCasePrivate_private.apinotes', not 'FrameworkWithWrongCasePrivate_Private.apinotes' +// CHECK-NOT: warning: diff --git a/clang/test/APINotes/extern-context.cpp b/clang/test/APINotes/extern-context.cpp new file mode 100644 index 000000000000..331dee002361 --- /dev/null +++ b/clang/test/APINotes/extern-context.cpp @@ -0,0 +1,23 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternC -x c++ | FileCheck -check-prefix=CHECK-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternCXX -x c++ | FileCheck -check-prefix=CHECK-EXTERN-CXX %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternC -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternCXX -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-CXX %s + +#include "ExternCtx.h" + +// CHECK-EXTERN-C: Dumping globalInExternC: +// CHECK-EXTERN-C: VarDecl {{.+}} imported in ExternCtx globalInExternC 'int' +// CHECK-EXTERN-C: UnavailableAttr {{.+}} <> "oh no" + +// CHECK-EXTERN-CXX: Dumping globalInExternCXX: +// CHECK-EXTERN-CXX: VarDecl {{.+}} imported in ExternCtx globalInExternCXX 'int' +// CHECK-EXTERN-CXX: UnavailableAttr {{.+}} <> "oh no #2" + +// CHECK-FUNC-EXTERN-C: Dumping globalFuncInExternC: +// CHECK-FUNC-EXTERN-C: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternC 'void ()' +// CHECK-FUNC-EXTERN-C: UnavailableAttr {{.+}} <> "oh no #3" + +// CHECK-FUNC-EXTERN-CXX: Dumping globalFuncInExternCXX: +// CHECK-FUNC-EXTERN-CXX: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternCXX 'void ()' +// CHECK-FUNC-EXTERN-CXX: UnavailableAttr {{.+}} <> "oh no #4" diff --git a/clang/test/APINotes/instancetype.m b/clang/test/APINotes/instancetype.m new file mode 100644 index 000000000000..30339e5386f6 --- /dev/null +++ b/clang/test/APINotes/instancetype.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -verify %s + +@import InstancetypeModule; + +void test() { + // The nullability is here to verify that the API notes were applied. + int good = [SomeSubclass instancetypeFactoryMethod]; // expected-error {{initializing 'int' with an expression of type 'SomeSubclass * _Nonnull'}} + int bad = [SomeSubclass staticFactoryMethod]; // expected-error {{initializing 'int' with an expression of type 'SomeBaseClass * _Nonnull'}} +} diff --git a/clang/test/APINotes/module-cache.m b/clang/test/APINotes/module-cache.m new file mode 100644 index 000000000000..5dcaf1181f9d --- /dev/null +++ b/clang/test/APINotes/module-cache.m @@ -0,0 +1,65 @@ +// RUN: rm -rf %t + +// Set up directories +// RUN: mkdir -p %t/APINotes +// RUN: cp %S/Inputs/APINotes/SomeOtherKit.apinotes %t/APINotes/SomeOtherKit.apinotes +// RUN: mkdir -p %t/Frameworks +// RUN: cp -r %S/Inputs/Frameworks/SomeOtherKit.framework %t/Frameworks + +// First build: check that 'methodB' is unavailable but 'methodA' is available. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Do it again; now we're using caches. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-WITHOUT-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Add a blank line to the header to force the module to rebuild, without +// (yet) changing API notes. +// RUN: echo >> %t/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Change the API notes file, after the module has rebuilt once. +// RUN: echo ' - Selector: "methodA"' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' MethodKind: Instance' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' Availability: none' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' AvailabilityMsg: "not here either"' >> %t/APINotes/SomeOtherKit.apinotes + +// Build again: check that both methods are now unavailable and that the module rebuilt. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/after.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODA %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-TWO-ERRORS %s < %t/after.log + +// Run the build again: check that both methods are now unavailable +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/after.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODA %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-WITHOUT-REBUILD %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-TWO-ERRORS %s < %t/after.log + +@import SomeOtherKit; + +void test(A *a) { + // CHECK-METHODA: error: 'methodA' is unavailable: not here either + [a methodA]; + + // CHECK-METHODB: error: 'methodB' is unavailable: anything but this + [a methodB]; +} + +// CHECK-REBUILD: remark: building module{{.*}}SomeOtherKit + +// CHECK-WITHOUT-REBUILD-NOT: remark: building module{{.*}}SomeOtherKit + +// CHECK-ONE-ERROR: 1 error generated. +// CHECK-TWO-ERRORS: 2 errors generated. + diff --git a/clang/test/APINotes/namespaces.cpp b/clang/test/APINotes/namespaces.cpp new file mode 100644 index 000000000000..2f9d93c2ea0e --- /dev/null +++ b/clang/test/APINotes/namespaces.cpp @@ -0,0 +1,69 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -x objective-c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::my_typedef -x objective-c++ | FileCheck -check-prefix=CHECK-TYPEDEF-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::my_using_decl -x objective-c++ | FileCheck -check-prefix=CHECK-USING-DECL-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::varInNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::funcInNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested2::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::funcInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::Namespace1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter varInInlineNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-INLINE-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter funcInInlineNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-INLINE-NAMESPACE %s + +#import + +// CHECK-TYPEDEF-IN-NAMESPACE: Dumping Namespace1::my_typedef: +// CHECK-TYPEDEF-IN-NAMESPACE-NEXT: TypedefDecl {{.+}} imported in Namespaces my_typedef 'int' +// CHECK-TYPEDEF-IN-NAMESPACE: SwiftNameAttr {{.+}} <> "SwiftTypedef" + +// CHECK-USING-DECL-IN-NAMESPACE: Dumping Namespace1::my_using_decl: +// CHECK-USING-DECL-IN-NAMESPACE-NEXT: TypeAliasDecl {{.+}} imported in Namespaces my_using_decl 'int' +// CHECK-USING-DECL-IN-NAMESPACE: SwiftNameAttr {{.+}} <> "SwiftUsingDecl" + +// CHECK-GLOBAL-IN-NAMESPACE: Dumping Namespace1::varInNamespace: +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNamespace 'int' static cinit +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 1 +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftVarInNamespace" + +// CHECK-FUNC-IN-NAMESPACE: Dumping Namespace1::funcInNamespace: +// CHECK-FUNC-IN-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInNamespace 'void ()' +// CHECK-FUNC-IN-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftFuncInNamespace()" + +// CHECK-STRUCT-IN-NAMESPACE: Dumping Namespace1::char_box: +// CHECK-STRUCT-IN-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct char_box +// CHECK-STRUCT-IN-NAMESPACE: SwiftNameAttr {{.+}} <> "CharBox" + +// CHECK-GLOBAL-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::varInNestedNamespace: +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNestedNamespace 'int' static cinit +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 1 +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftVarInNestedNamespace" + +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested2::varInNestedNamespace: +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNestedNamespace 'int' static cinit +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 2 +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftAnotherVarInNestedNamespace" + +// CHECK-FUNC-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::funcInNestedNamespace: +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInNestedNamespace 'void (int)' +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: ParmVarDecl {{.+}} i 'int' +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftFuncInNestedNamespace(_:)" + +// CHECK-STRUCT-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::char_box: +// CHECK-STRUCT-IN-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct char_box +// CHECK-STRUCT-IN-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <> "NestedCharBox" + +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE: Dumping Namespace1::Nested1::Namespace1::char_box: +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct char_box +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <> "DeepNestedCharBox" + +// CHECK-GLOBAL-IN-INLINE-NAMESPACE: Dumping varInInlineNamespace: +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInInlineNamespace 'int' static cinit +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 3 +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftVarInInlineNamespace" + +// CHECK-FUNC-IN-INLINE-NAMESPACE: Dumping funcInInlineNamespace: +// CHECK-FUNC-IN-INLINE-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInInlineNamespace 'void ()' +// CHECK-FUNC-IN-INLINE-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <> "swiftFuncInInlineNamespace()" diff --git a/clang/test/APINotes/nullability.c b/clang/test/APINotes/nullability.c new file mode 100644 index 000000000000..e07fc2e5c117 --- /dev/null +++ b/clang/test/APINotes/nullability.c @@ -0,0 +1,21 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" + +int main() { + custom_realloc(0, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + int i = 0; + do_something_with_pointers(&i, 0); + do_something_with_pointers(0, &i); // expected-warning{{null passed to a callee that requires a non-null argument}} + + extern void *p; + do_something_with_arrays(0, p); // expected-warning{{null passed to a callee that requires a non-null argument}} + do_something_with_arrays(p, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + + take_pointer_and_int(0, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + + float *fp = global_int; // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'int * _Nonnull'}} + return 0; +} + diff --git a/clang/test/APINotes/nullability.m b/clang/test/APINotes/nullability.m new file mode 100644 index 000000000000..21ec6680fa71 --- /dev/null +++ b/clang/test/APINotes/nullability.m @@ -0,0 +1,46 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +// Test with Swift version 3.0. This should only affect the few APIs that have an entry in the 3.0 tables. + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fapinotes-swift-version=3.0 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify -DSWIFT_VERSION_3_0 -fmodules-ignore-macro=SWIFT_VERSION_3_0 + +#import + +int main() { + A *a; + +#if SWIFT_VERSION_3_0 + float *fp = // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'A * _Nullable'}} + [a transform: 0 integer: 0]; +#else + float *fp = // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'A *'}} + [a transform: 0 integer: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} +#endif + + [a setNonnullAInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [A setNonnullAInstance: 0]; // no warning + a.nonnullAInstance = 0; // expected-warning{{null passed to a callee that requires a non-null argument}} + A* _Nonnull aPtr = a.nonnullAInstance; // no warning + + [a setNonnullAClass: 0]; // no warning + [A setNonnullAClass: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + + [a setNonnullABoth: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [A setNonnullABoth: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + + [a setInternalProperty: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + +#if SWIFT_VERSION_3_0 + // Version 3 information overrides header information. + [a setExplicitNonnullInstance: 0]; // okay + [a setExplicitNullableInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} +#else + // Header information overrides unversioned information. + [a setExplicitNonnullInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [a setExplicitNullableInstance: 0]; // okay +#endif + + return 0; +} + diff --git a/clang/test/APINotes/objc-forward-declarations.m b/clang/test/APINotes/objc-forward-declarations.m new file mode 100644 index 000000000000..e82bed205550 --- /dev/null +++ b/clang/test/APINotes/objc-forward-declarations.m @@ -0,0 +1,12 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -F %S/Inputs/Frameworks %s -verify + +@import LayeredKit; + +void test( + UpwardClass *okayClass, + id okayProto, + PerfectlyNormalClass *badClass // expected-error {{'PerfectlyNormalClass' is unavailable}} +) { + // expected-note@LayeredKitImpl/LayeredKitImpl.h:4 {{'PerfectlyNormalClass' has been explicitly marked unavailable here}} +} diff --git a/clang/test/APINotes/objc_designated_inits.m b/clang/test/APINotes/objc_designated_inits.m new file mode 100644 index 000000000000..1f2b8ed534b7 --- /dev/null +++ b/clang/test/APINotes/objc_designated_inits.m @@ -0,0 +1,17 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" +#import + +@interface CSub : C +-(instancetype)initWithA:(A*)a; +@end + +@implementation CSub +-(instancetype)initWithA:(A*)a { // expected-warning{{designated initializer missing a 'super' call to a designated initializer of the super class}} + // expected-note@SomeKit/SomeKit.h:20 2{{method marked as designated initializer of the class here}} + self = [super init]; // expected-warning{{designated initializer invoked a non-designated initializer}} + return self; +} +@end diff --git a/clang/test/APINotes/properties.m b/clang/test/APINotes/properties.m new file mode 100644 index 000000000000..f218092a66e1 --- /dev/null +++ b/clang/test/APINotes/properties.m @@ -0,0 +1,42 @@ +// RUN: rm -rf %t && mkdir -p %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fblocks -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'TestProperties::' | FileCheck -check-prefix=CHECK -check-prefix=CHECK-4 %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fblocks -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'TestProperties::' -fapinotes-swift-version=3 | FileCheck -check-prefix=CHECK -check-prefix=CHECK-3 %s + +@import VersionedKit; + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnly 'id' +// CHECK-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClass 'id' +// CHECK-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyInVersion3 'id' +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}} +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassInVersion3 'id' +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}} +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyExceptInVersion3 'id' +// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassExceptInVersion3 'id' +// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <> +// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} +// CHECK-NOT: Attr + +// CHECK-LABEL: Decl diff --git a/clang/test/APINotes/retain-count-convention.m b/clang/test/APINotes/retain-count-convention.m new file mode 100644 index 000000000000..4bf9610a352a --- /dev/null +++ b/clang/test/APINotes/retain-count-convention.m @@ -0,0 +1,38 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fdisable-module-hash -fsyntax-only -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/SimpleKit.pcm | FileCheck %s +// RUN: %clang_cc1 -ast-dump -ast-dump-filter 'DUMP' %t/ModulesCache/SimpleKit.pcm | FileCheck -check-prefix CHECK-DUMP %s + +#import + +// CHECK: void *getCFOwnedToUnowned(void) __attribute__((cf_returns_not_retained)); +// CHECK: void *getCFUnownedToOwned(void) __attribute__((cf_returns_retained)); +// CHECK: void *getCFOwnedToNone(void) __attribute__((cf_unknown_transfer)); +// CHECK: id getObjCOwnedToUnowned(void) __attribute__((ns_returns_not_retained)); +// CHECK: id getObjCUnownedToOwned(void) __attribute__((ns_returns_retained)); +// CHECK: int indirectGetCFOwnedToUnowned(void * _Nullable *out __attribute__((cf_returns_not_retained))); +// CHECK: int indirectGetCFUnownedToOwned(void * _Nullable *out __attribute__((cf_returns_retained))); +// CHECK: int indirectGetCFOwnedToNone(void * _Nullable *out); +// CHECK: int indirectGetCFNoneToOwned(void **out __attribute__((cf_returns_not_retained))); + +// CHECK-LABEL: @interface MethodTest +// CHECK: - (id)getOwnedToUnowned __attribute__((ns_returns_not_retained)); +// CHECK: - (id)getUnownedToOwned __attribute__((ns_returns_retained)); +// CHECK: @end + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToUnowned_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFReturnsNotRetainedAttr +// CHECK-DUMP-NEXT: CFAuditedTransferAttr +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToOwned_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFReturnsRetainedAttr +// CHECK-DUMP-NEXT: CFAuditedTransferAttr +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToNone_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFUnknownTransferAttr +// CHECK-DUMP-NOT: Attr diff --git a/clang/test/APINotes/search-order.m b/clang/test/APINotes/search-order.m new file mode 100644 index 000000000000..17e81d5eb2d6 --- /dev/null +++ b/clang/test/APINotes/search-order.m @@ -0,0 +1,25 @@ +// RUN: rm -rf %t && mkdir -p %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_FRAMEWORK=1 -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %S/Inputs/APINotes -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_SEARCH_PATH=1 -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -iapinotes-modules %S/Inputs/APINotes -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_FRAMEWORK=1 -verify + +@import SomeOtherKit; + +void test(A *a) { +#if FROM_FRAMEWORK + [a methodA]; // expected-error{{unavailable}} + [a methodB]; + + // expected-note@SomeOtherKit/SomeOtherKit.h:5{{'methodA' has been explicitly marked unavailable here}} +#elif FROM_SEARCH_PATH + [a methodA]; + [a methodB]; // expected-error{{unavailable}} + + // expected-note@SomeOtherKit/SomeOtherKit.h:6{{'methodB' has been explicitly marked unavailable here}} +#else +# error Not something we need to test +#endif +} diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp new file mode 100644 index 000000000000..904857e58593 --- /dev/null +++ b/clang/test/APINotes/swift-import-as.cpp @@ -0,0 +1,16 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter ImmortalRefType | FileCheck -check-prefix=CHECK-IMMORTAL %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedType | FileCheck -check-prefix=CHECK-REF-COUNTED %s + +#include + +// CHECK-IMMORTAL: Dumping ImmortalRefType: +// CHECK-IMMORTAL-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct ImmortalRefType +// CHECK-IMMORTAL: SwiftAttrAttr {{.+}} <> "import_reference" + +// CHECK-REF-COUNTED: Dumping RefCountedType: +// CHECK-REF-COUNTED-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct RefCountedType +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "import_reference" +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "retain:RCRetain" +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <> "release:RCRelease" diff --git a/clang/test/APINotes/top-level-private-modules.c b/clang/test/APINotes/top-level-private-modules.c new file mode 100644 index 000000000000..0da72b2e36f4 --- /dev/null +++ b/clang/test/APINotes/top-level-private-modules.c @@ -0,0 +1,8 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include +#include + +void *testPlain = PrivateLib; // expected-error {{initializing 'void *' with an expression of incompatible type 'float'}} +void *testFramework = TopLevelPrivateKit_Private; // expected-error {{initializing 'void *' with an expression of incompatible type 'float'}} diff --git a/clang/test/APINotes/types.m b/clang/test/APINotes/types.m new file mode 100644 index 000000000000..133d504713d7 --- /dev/null +++ b/clang/test/APINotes/types.m @@ -0,0 +1,28 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fdisable-module-hash -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify +// RUN: %clang_cc1 -ast-print %t/ModulesCache/SimpleKit.pcm | FileCheck %s + +#import +#import + +// CHECK: struct __attribute__((swift_name("SuccessfullyRenamedA"))) RenamedAgainInAPINotesA { +// CHECK: struct __attribute__((swift_name("SuccessfullyRenamedB"))) RenamedAgainInAPINotesB { + +void test(OverriddenTypes *overridden) { + int *ip1 = global_int_ptr; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double (*)(int, int)'}} + + int *ip2 = global_int_fun( // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}} + ip2, // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'double *'}} + ip2); // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'float *'}} + + int *ip3 = [overridden // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}} + methodToMangle: ip3 // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'double *'}} + second: ip3]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'float *'}} + + int *ip4 = overridden.intPropertyToMangle; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double *'}} +} + +// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr' here}} +// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr2' here}} +// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr1' here}} +// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr2' here}} diff --git a/clang/test/APINotes/versioned-multi.c b/clang/test/APINotes/versioned-multi.c new file mode 100644 index 000000000000..48c51fd932e1 --- /dev/null +++ b/clang/test/APINotes/versioned-multi.c @@ -0,0 +1,69 @@ +// RUN: rm -rf %t && mkdir -p %t + +// Build and check the unversioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-UNVERSIONED %s + +// Build and check the various versions. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned3 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned3/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-3 %s + +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned4 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=4 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned4/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-4 %s + +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned5 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=5 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned5/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-5 %s + +#import + +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_NEW"))); + +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4 __attribute__((swift_name("MultiVersionedTypedef4_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34 __attribute__((swift_name("MultiVersionedTypedef34_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_3"))); + +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4 __attribute__((swift_name("MultiVersionedTypedef4_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34 __attribute__((swift_name("MultiVersionedTypedef34_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_4"))); + +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4; +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34; +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_5"))); diff --git a/clang/test/APINotes/versioned.m b/clang/test/APINotes/versioned.m new file mode 100644 index 000000000000..61cc8c3f7c4d --- /dev/null +++ b/clang/test/APINotes/versioned.m @@ -0,0 +1,187 @@ +// RUN: rm -rf %t && mkdir -p %t + +// Build and check the unversioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-UNVERSIONED %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP -check-prefix=CHECK-UNVERSIONED-DUMP %s + +// Build and check the versioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP -check-prefix=CHECK-VERSIONED-DUMP %s + +#import + +// CHECK-UNVERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)"))); +// CHECK-VERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(a:b:)"))); + +// CHECK-DUMP-LABEL: Dumping moveToPointDUMP +// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "moveTo(x:y:)" +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "moveTo(a:b:)" +// CHECK-UNVERSIONED-DUMP: SwiftNameAttr {{.+}} "moveTo(x:y:)" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "moveTo(a:b:)" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping unversionedRenameDUMP +// CHECK-DUMP: in VersionedKit unversionedRenameDUMP +// CHECK-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 0 IsReplacedByActive{{$}} +// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_HEADER()" +// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_NOTES()" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping TestGenericDUMP +// CHECK-VERSIONED-DUMP: SwiftImportAsNonGenericAttr {{.+}} <> +// CHECK-UNVERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftImportAsNonGenericAttr {{.+}} <> +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift3RenamedOnlyDUMP +// CHECK-DUMP: in VersionedKit Swift3RenamedOnlyDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "SpecialSwift3Name" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift3RenamedAlsoDUMP +// CHECK-DUMP: in VersionedKit Swift3RenamedAlsoDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "Swift4Name" +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Also" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "Swift4Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "SpecialSwift3Also" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift4RenamedDUMP +// CHECK-DUMP: in VersionedKit Swift4RenamedDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 4 {{[0-9]+}} IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift4Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 4{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <> "SpecialSwift4Name" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-NOT: Dumping + +// CHECK-UNVERSIONED: void acceptClosure(void (^block)(void) __attribute__((noescape))); +// CHECK-VERSIONED: void acceptClosure(void (^block)(void)); + +// CHECK-UNVERSIONED: void privateFunc(void) __attribute__((swift_private)); + +// CHECK-UNVERSIONED: typedef double MyDoubleWrapper __attribute__((swift_wrapper("struct"))); + +// CHECK-UNVERSIONED: enum __attribute__((ns_error_domain(MyErrorDomain))) MyErrorCode { +// CHECK-UNVERSIONED-NEXT: MyErrorCodeFailed = 1 +// CHECK-UNVERSIONED-NEXT: }; + +// CHECK-UNVERSIONED: __attribute__((swift_bridge("MyValueType"))) +// CHECK-UNVERSIONED: @interface MyReferenceType + +// CHECK-VERSIONED: void privateFunc(void); + +// CHECK-VERSIONED: typedef double MyDoubleWrapper; + +// CHECK-VERSIONED: enum MyErrorCode { +// CHECK-VERSIONED-NEXT: MyErrorCodeFailed = 1 +// CHECK-VERSIONED-NEXT: }; + +// CHECK-VERSIONED-NOT: __attribute__((swift_bridge("MyValueType"))) +// CHECK-VERSIONED: @interface MyReferenceType + +// CHECK-UNVERSIONED: __attribute__((swift_objc_members) +// CHECK-UNVERSIONED-NEXT: @interface TestProperties +// CHECK-VERSIONED-NOT: __attribute__((swift_objc_members) +// CHECK-VERSIONED: @interface TestProperties + +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) FlagEnum { +// CHECK-UNVERSIONED-NEXT: FlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: FlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) NewlyFlagEnum { +// CHECK-UNVERSIONED-NEXT: NewlyFlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: NewlyFlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) APINotedFlagEnum { +// CHECK-UNVERSIONED-NEXT: APINotedFlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: APINotedFlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenEnum { +// CHECK-UNVERSIONED-NEXT: OpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) NewlyOpenEnum { +// CHECK-UNVERSIONED-NEXT: NewlyOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) NewlyClosedEnum { +// CHECK-UNVERSIONED-NEXT: NewlyClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) ClosedToOpenEnum { +// CHECK-UNVERSIONED-NEXT: ClosedToOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) OpenToClosedEnum { +// CHECK-UNVERSIONED-NEXT: OpenToClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) APINotedOpenEnum { +// CHECK-UNVERSIONED-NEXT: APINotedOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) APINotedClosedEnum { +// CHECK-UNVERSIONED-NEXT: APINotedClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; + +// CHECK-VERSIONED-LABEL: enum __attribute__((flag_enum)) FlagEnum { +// CHECK-VERSIONED-NEXT: FlagEnumA = 1, +// CHECK-VERSIONED-NEXT: FlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyFlagEnum { +// CHECK-VERSIONED-NEXT: NewlyFlagEnumA = 1, +// CHECK-VERSIONED-NEXT: NewlyFlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((flag_enum)) APINotedFlagEnum { +// CHECK-VERSIONED-NEXT: APINotedFlagEnumA = 1, +// CHECK-VERSIONED-NEXT: APINotedFlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenEnum { +// CHECK-VERSIONED-NEXT: OpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyOpenEnum { +// CHECK-VERSIONED-NEXT: NewlyOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyClosedEnum { +// CHECK-VERSIONED-NEXT: NewlyClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) ClosedToOpenEnum { +// CHECK-VERSIONED-NEXT: ClosedToOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenToClosedEnum { +// CHECK-VERSIONED-NEXT: OpenToClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) APINotedOpenEnum { +// CHECK-VERSIONED-NEXT: APINotedOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) APINotedClosedEnum { +// CHECK-VERSIONED-NEXT: APINotedClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; + +// These don't actually have versioned information, so we just check them once. +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) SoonToBeCFEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) SoonToBeNSEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) __attribute__((flag_enum)) SoonToBeCFOptions { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFOptionsA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) __attribute__((flag_enum)) SoonToBeNSOptions { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSOptionsA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) SoonToBeCFClosedEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) SoonToBeNSClosedEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum UndoAllThatHasBeenDoneToMe { +// CHECK-UNVERSIONED-NEXT: UndoAllThatHasBeenDoneToMeA = 1 +// CHECK-UNVERSIONED-NEXT: }; diff --git a/clang/test/APINotes/yaml-convert-diags.c b/clang/test/APINotes/yaml-convert-diags.c new file mode 100644 index 000000000000..1d352dc2c523 --- /dev/null +++ b/clang/test/APINotes/yaml-convert-diags.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: not %clang_cc1 -fsyntax-only -fapinotes %s -I %S/Inputs/BrokenHeaders2 2>&1 | FileCheck %s + +#include "SomeBrokenLib.h" + +// CHECK: error: multiple definitions of global function 'do_something_with_pointers' diff --git a/clang/test/APINotes/yaml-parse-diags.c b/clang/test/APINotes/yaml-parse-diags.c new file mode 100644 index 000000000000..3ae39ccb301d --- /dev/null +++ b/clang/test/APINotes/yaml-parse-diags.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fapinotes %s -I %S/Inputs/BrokenHeaders -verify + +#include "SomeBrokenLib.h" + +// expected-error@APINotes.apinotes:4{{unknown key 'Nu llabilityOfRet'}} diff --git a/clang/test/APINotes/yaml-reader-errors.m b/clang/test/APINotes/yaml-reader-errors.m new file mode 100644 index 000000000000..9e5ee34c3e41 --- /dev/null +++ b/clang/test/APINotes/yaml-reader-errors.m @@ -0,0 +1,5 @@ +// RUN: rm -rf %t +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fapinotes -fapinotes-modules -fmodules-cache-path=%t -I %S/Inputs/yaml-reader-errors/ -fsyntax-only %s > %t.err 2>&1 +// RUN: FileCheck %S/Inputs/yaml-reader-errors/UIKit.apinotes < %t.err + +@import UIKit; -- GitLab From b343b02a88821cab320e7d9976a05eabd0df29ec Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 27 Mar 2024 13:14:36 +0000 Subject: [PATCH 058/541] [gn build] Port 4f9aab2b500d --- llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn index c0ea62716fd2..daa3278d56d7 100644 --- a/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn @@ -18,9 +18,11 @@ static_library("Common") { "DAGISelMatcher.cpp", "GlobalISel/CXXPredicates.cpp", "GlobalISel/CodeExpander.cpp", + "GlobalISel/CombinerUtils.cpp", "GlobalISel/GlobalISelMatchTable.cpp", "GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp", "GlobalISel/MatchDataInfo.cpp", + "GlobalISel/PatternParser.cpp", "GlobalISel/Patterns.cpp", "InfoByHwMode.cpp", "OptEmitter.cpp", -- GitLab From 2fa46ca922178ec049006a1b4851058400cbada9 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 27 Mar 2024 06:25:10 -0700 Subject: [PATCH 059/541] [workflows] Update the version of the scorecard-action (#86753) I'm hoping this will fix the errors we've been seeing the last few days: 2024-03-19T20:44:07.4841482Z 2024/03/19 20:44:07 error signing scorecard json results: error signing payload: getting key from Fulcio: verifying SCT: updating local metadata and targets: error updating to TUF remote mirror: invalid key --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b8e8ab26c3ff..ff61cf83a6af 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -36,7 +36,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif -- GitLab From 6e6d266fb8cc1398e7d5a220a9332d88ce074464 Mon Sep 17 00:00:00 2001 From: zibi2 <62662650+zibi2@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:50:25 -0400 Subject: [PATCH 060/541] [libc++] Fix one case in saturate_cast.pass.cpp for 64-bit on z/OS (#86724) On z/OS int128 is disabled causing one of the cases in `saturate_cast.pass.cpp` to fail. The failure is only in 64-bit mode. In this case `the std::numeric_limits::max()` is within `std::numeric_limits::min()` and `std::numeric_limits::max()` therefore, saturate_cast( sBigMax) == LONG_MAX and not ULONG_MAX as original test. In 32-bit, `saturate_cast( sBigMax) == ULONG_MAX` like on other platforms where int128 is enabled. This PR is required to pass this test case on z/OS and possibly on other platforms where int128 is not supported/enabled. --------- Co-authored-by: Sean Perry --- .../numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp index c06a9ed2d5cb..cbca37e3a661 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp @@ -329,7 +329,7 @@ constexpr bool test() { { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == 0UL); // saturated assert(std::saturate_cast( sZero) == 0UL); - assert(std::saturate_cast( sBigMax) == ULONG_MAX); // saturated + assert(std::saturate_cast( sBigMax) == (sizeof(UIntT) > sizeof(unsigned long int) ? ULONG_MAX : LONG_MAX)); // saturated depending on underlying types { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == 0UL); -- GitLab From 2cb7ea1553a5c7be81bee4ed3c51b7727b9d2ee8 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Wed, 27 Mar 2024 07:02:12 -0700 Subject: [PATCH 061/541] [lldb][nfc] Delete unused variable (#86740) This was made unused by d9ec4b24a84addb8bd77b5d9dd990181351cf84c. --- lldb/source/Target/StackFrame.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 3af62f52d575..03a74f29e76e 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1800,7 +1800,6 @@ void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, return; ExecutionContext exe_ctx(shared_from_this()); - StreamString s; const FormatEntity::Entry *frame_format = nullptr; Target *target = exe_ctx.GetTargetPtr(); -- GitLab From f5296df97c6bdc6cb658691e5863fdbf336d4430 Mon Sep 17 00:00:00 2001 From: "Kevin P. Neal" <52762977+kpneal@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:20:00 -0400 Subject: [PATCH 062/541] [FPEnv][AMDGPU] Correct AMDGPUSimplifyLibCalls handling of strictfp attribute. (#86705) The AMDGPUSimplifyLibCalls pass was lowering function calls with the strictfp attribute to sequences that included function calls incorrectly lacking the attribute. This patch corrects that. The pass now also emits the correct constrained fp call instead of normal FP instructions when in a function with the strictfp attribute. Replacing non-constrained calls with constrained calls when required is still on the IRBuilder's TODO list. --- llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp | 2 ++ .../CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll | 12 ++++++------ .../CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp index 84b4ccc1ae7b..5aa35becd842 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -657,6 +657,8 @@ bool AMDGPULibCalls::fold(CallInst *CI) { return true; IRBuilder<> B(CI); + if (CI->isStrictFP()) + B.setIsFPConstrained(true); if (FPMathOperator *FPOp = dyn_cast(CI)) { // Under unsafe-math, evaluate calls if possible. diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll index 942f459ea6b8..8ddaf243db92 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll @@ -808,7 +808,7 @@ define float @test_pown_fast_f32_nobuiltin(float %x, i32 %y) { ; CHECK-LABEL: define float @test_pown_fast_f32_nobuiltin ; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call fast float @_Z4pownfi(float [[X]], i32 [[Y]]) #[[ATTR3:[0-9]+]] +; CHECK-NEXT: [[CALL:%.*]] = tail call fast float @_Z4pownfi(float [[X]], i32 [[Y]]) #[[ATTR4:[0-9]+]] ; CHECK-NEXT: ret float [[CALL]] ; entry: @@ -820,11 +820,11 @@ define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 { ; CHECK-LABEL: define float @test_pown_fast_f32_strictfp ; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]]) -; CHECK-NEXT: [[__LOG2:%.*]] = call fast float @llvm.log2.f32(float [[__FABS]]) -; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to float -; CHECK-NEXT: [[__YLOGX:%.*]] = fmul fast float [[__LOG2]], [[POWNI2F]] -; CHECK-NEXT: [[__EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[__YLOGX]]) +; CHECK-NEXT: [[__FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]]) #[[ATTR0]] +; CHECK-NEXT: [[__LOG2:%.*]] = call fast float @llvm.log2.f32(float [[__FABS]]) #[[ATTR0]] +; CHECK-NEXT: [[POWNI2F:%.*]] = call fast float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: [[__YLOGX:%.*]] = call fast float @llvm.experimental.constrained.fmul.f32(float [[POWNI2F]], float [[__LOG2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: [[__EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[__YLOGX]]) #[[ATTR0]] ; CHECK-NEXT: [[__YEVEN:%.*]] = shl i32 [[Y]], 31 ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll index 2ffa647d1869..2e64a3456c24 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll @@ -896,7 +896,7 @@ define float @test_rootn_f32__y_neg2__strictfp(float %x) #1 { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2__strictfp( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]]) #[[ATTR0]] ; CHECK-NEXT: ret float [[__ROOTN2RSQRT]] ; entry: -- GitLab From b43ec8e62b5f5a39be378c460339217511261400 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 27 Mar 2024 07:16:50 -0700 Subject: [PATCH 063/541] [SLP]Fix PR86798: handle phi nodes being trunced, but not its operands. If the phi node is trunced, but not its operand(s), need to handle this situation in the assertion, code already does the right transformation. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 3 +- .../X86/phi-node-bitwidt-op-not.ll | 95 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index fbf1cb6a976f..e1f26b922dbe 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -11926,7 +11926,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { Builder.SetCurrentDebugLocation(PH->getDebugLoc()); Value *Vec = vectorizeOperand(E, I, /*PostponedPHIs=*/true); if (VecTy != Vec->getType()) { - assert((getOperandEntry(E, I)->State == TreeEntry::NeedToGather || + assert((It != MinBWs.end() || + getOperandEntry(E, I)->State == TreeEntry::NeedToGather || MinBWs.contains(getOperandEntry(E, I))) && "Expected item in MinBWs."); Vec = Builder.CreateIntCast(Vec, VecTy, GetOperandSignedness(I)); diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll new file mode 100644 index 000000000000..f376ca71c776 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll @@ -0,0 +1,95 @@ +; 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 < %s | FileCheck %s + +define i32 @test(ptr %b, ptr %c, i32 %0, ptr %a, i1 %tobool3.not) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ptr [[B:%.*]], ptr [[C:%.*]], i32 [[TMP0:%.*]], ptr [[A:%.*]], i1 [[TOBOOL3_NOT:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[TOBOOL3_NOT]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = ashr <4 x i32> [[TMP2]], +; CHECK-NEXT: [[TMP4:%.*]] = icmp slt <4 x i32> [[TMP3]], [[TMP2]] +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i1> [[TMP4]] to <4 x i16> +; CHECK-NEXT: br label [[BB3:%.*]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt <4 x i32> [[TMP7]], zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = zext <4 x i1> [[TMP8]] to <4 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = insertelement <4 x i1> poison, i1 [[TOBOOL3_NOT]], i32 0 +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i1> [[TMP10]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[TMP11]], <4 x i32> [[TMP7]], <4 x i32> [[TMP9]] +; CHECK-NEXT: [[TMP13:%.*]] = shl <4 x i32> [[TMP12]], +; CHECK-NEXT: [[TMP14:%.*]] = ashr <4 x i32> [[TMP13]], +; CHECK-NEXT: [[TMP15:%.*]] = trunc <4 x i32> [[TMP14]] to <4 x i16> +; CHECK-NEXT: br i1 true, label [[BB3]], label [[BB2]] +; CHECK: bb3: +; CHECK-NEXT: [[TMP16:%.*]] = phi <4 x i16> [ [[TMP5]], [[BB1]] ], [ [[TMP15]], [[BB2]] ] +; CHECK-NEXT: [[TMP17:%.*]] = extractelement <4 x i16> [[TMP16]], i32 0 +; CHECK-NEXT: [[TMP18:%.*]] = sext i16 [[TMP17]] to i32 +; CHECK-NEXT: store i32 [[TMP18]], ptr [[B]], align 16 +; CHECK-NEXT: [[TMP19:%.*]] = extractelement <4 x i16> [[TMP16]], i32 1 +; CHECK-NEXT: [[TMP20:%.*]] = sext i16 [[TMP19]] to i32 +; CHECK-NEXT: store i32 [[TMP20]], ptr [[A]], align 8 +; CHECK-NEXT: [[TMP21:%.*]] = extractelement <4 x i16> [[TMP16]], i32 2 +; CHECK-NEXT: [[TMP22:%.*]] = sext i16 [[TMP21]] to i32 +; CHECK-NEXT: store i32 [[TMP22]], ptr [[C]], align 16 +; CHECK-NEXT: [[TMP23:%.*]] = extractelement <4 x i16> [[TMP16]], i32 3 +; CHECK-NEXT: [[TMP24:%.*]] = sext i16 [[TMP23]] to i32 +; CHECK-NEXT: store i32 [[TMP24]], ptr [[B]], align 8 +; CHECK-NEXT: ret i32 0 +; +entry: + br i1 %tobool3.not, label %bb1, label %bb2 + +bb1: + %conv1.i.us = ashr i32 %0, 16 + %cmp2.i.us = icmp slt i32 %conv1.i.us, %0 + %sext26.us = zext i1 %cmp2.i.us to i32 + %conv1.i.us.5 = ashr i32 %0, 16 + %cmp2.i.us.5 = icmp slt i32 %conv1.i.us.5, %0 + %sext26.us.5 = zext i1 %cmp2.i.us.5 to i32 + %conv1.i.us.6 = ashr i32 %0, 16 + %cmp2.i.us.6 = icmp slt i32 %conv1.i.us.6, %0 + %sext26.us.6 = zext i1 %cmp2.i.us.6 to i32 + %conv1.i.us.7 = ashr i32 %0, 16 + %cmp2.i.us.7 = icmp slt i32 %conv1.i.us.7, %0 + %sext26.us.7 = zext i1 %cmp2.i.us.7 to i32 + br label %bb3 + +bb2: + %cmp2.i = icmp sgt i32 %0, 0 + %1 = zext i1 %cmp2.i to i32 + %cond.i = select i1 %tobool3.not, i32 %0, i32 %1 + %sext26 = shl i32 %cond.i, 16 + %conv13 = ashr i32 %sext26, 16 + %cmp2.i.5 = icmp sgt i32 %0, 0 + %2 = zext i1 %cmp2.i.5 to i32 + %cond.i.5 = select i1 %tobool3.not, i32 %0, i32 %2 + %sext26.5 = shl i32 %cond.i.5, 16 + %conv13.5 = ashr i32 %sext26.5, 16 + %cmp2.i.6 = icmp sgt i32 %0, 0 + %3 = zext i1 %cmp2.i.6 to i32 + %cond.i.6 = select i1 %tobool3.not, i32 %0, i32 %3 + %sext26.6 = shl i32 %cond.i.6, 16 + %conv13.6 = ashr i32 %sext26.6, 16 + %cmp2.i.7 = icmp sgt i32 %0, 0 + %4 = zext i1 %cmp2.i.7 to i32 + %cond.i.7 = select i1 %tobool3.not, i32 %0, i32 %4 + %sext26.7 = shl i32 %cond.i.7, 16 + %conv13.7 = ashr i32 %sext26.7, 16 + br i1 true, label %bb3, label %bb2 + +bb3: + %conv13p = phi i32 [ %sext26.us, %bb1 ], [ %conv13, %bb2 ] + %conv13.5p = phi i32 [ %sext26.us.5, %bb1 ], [ %conv13.5, %bb2 ] + %conv13.6p = phi i32 [ %sext26.us.6, %bb1 ], [ %conv13.6, %bb2 ] + %conv13.7p = phi i32 [ %sext26.us.7, %bb1 ], [ %conv13.7, %bb2 ] + store i32 %conv13p, ptr %b, align 16 + store i32 %conv13.5p, ptr %a, align 8 + store i32 %conv13.6p, ptr %c, align 16 + store i32 %conv13.7p, ptr %b, align 8 + ret i32 0 +} -- GitLab From 11b20d7ab09511d9e2bcd40606dfd3b31976efe0 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 27 Mar 2024 15:31:55 +0100 Subject: [PATCH 064/541] [clang] Fix an out-of-bound crash when checking template partial specializations. (#86794) I found this issue (a separate one) during the investigation of #86757, the crash is similar in substituteParameterMappings, but at different inner places. This was an out-of-bound issue where we access front element in an empty written template argument list to get the instantiation source range. This patch fixes it by adding a proper guard. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaConcept.cpp | 12 ++++++++++-- clang/test/SemaTemplate/concepts.cpp | 10 +++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0dd026a5de5c..0fdd9e3fb3ee 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -454,6 +454,7 @@ Bug Fixes to C++ Support - Fix a crash when instantiating a lambda that captures ``this`` outside of its context. Fixes (#GH85343). - Fix an issue where a namespace alias could be defined using a qualified name (all name components following the first `::` were ignored). +- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 1c546e9f5894..b6c4d3d540ef 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1269,10 +1269,18 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N, : SourceLocation())); Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); } + SourceLocation InstLocBegin = + ArgsAsWritten->arguments().empty() + ? ArgsAsWritten->getLAngleLoc() + : ArgsAsWritten->arguments().front().getSourceRange().getBegin(); + SourceLocation InstLocEnd = + ArgsAsWritten->arguments().empty() + ? ArgsAsWritten->getRAngleLoc() + : ArgsAsWritten->arguments().front().getSourceRange().getEnd(); Sema::InstantiatingTemplate Inst( - S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), + S, InstLocBegin, Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, - ArgsAsWritten->arguments().front().getSourceRange()); + {InstLocBegin, InstLocEnd}); if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) return true; diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index b7ea0d003a52..787cc809e253 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -verify %s +// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify %s namespace PR47043 { template concept True = true; @@ -1114,3 +1114,11 @@ void foo() { } } // namespace GH64808 + +namespace GH86757_1 { +template concept b = false; +template concept c = b<>; +template concept f = c< d >; +template struct e; // expected-note {{}} +template struct e; // expected-error {{class template partial specialization is not more specialized than the primary template}} +} -- GitLab From 9f84594e4ef87a50d1599814ba99fb735da76826 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Wed, 27 Mar 2024 10:33:25 -0400 Subject: [PATCH 065/541] [lldb][Dwarf] Add missing timer when parsing .debug_abbrev. (#86568) The time spent on parsing `.debug_abbrev` is also part of debug info parsing time. --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 5f67658f86ea..1164bc62682a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -693,6 +693,7 @@ llvm::DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { if (debug_abbrev_data.GetByteSize() == 0) return nullptr; + ElapsedTime elapsed(m_parse_time); auto abbr = std::make_unique(debug_abbrev_data.GetAsLLVM()); llvm::Error error = abbr->parse(); -- GitLab From 6d3ec56d3ce1478ac42a400a80532b8f732477fe Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 14:40:30 +0000 Subject: [PATCH 066/541] [X86] combineExtractWithShuffle - use combineExtractFromVectorLoad to extract scalar load from shuffled vector load Improves #85419 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 6 + llvm/test/CodeGen/X86/extractelement-load.ll | 118 ++- llvm/test/CodeGen/X86/masked_store.ll | 714 +++++++------------ llvm/test/CodeGen/X86/shrink_vmul.ll | 223 +++--- 4 files changed, 397 insertions(+), 664 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 4cd0bebe01bb..a229f6e55a98 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -44234,6 +44234,12 @@ static SDValue combineExtractWithShuffle(SDNode *N, SelectionDAG &DAG, if (SDValue V = GetLegalExtract(SrcOp, ExtractVT, ExtractIdx)) return DAG.getZExtOrTrunc(V, dl, VT); + if (N->getOpcode() == ISD::EXTRACT_VECTOR_ELT && ExtractVT == SrcVT && + SrcOp.getValueType() == SrcVT) + if (SDValue V = + combineExtractFromVectorLoad(N, SrcOp, ExtractIdx, dl, DAG, DCI)) + return V; + return SDValue(); } diff --git a/llvm/test/CodeGen/X86/extractelement-load.ll b/llvm/test/CodeGen/X86/extractelement-load.ll index e3e1cdcd7f56..ba2217f704bd 100644 --- a/llvm/test/CodeGen/X86/extractelement-load.ll +++ b/llvm/test/CodeGen/X86/extractelement-load.ll @@ -10,20 +10,13 @@ define i32 @t(ptr %val) nounwind { ; X86-SSE2-LABEL: t: ; X86-SSE2: # %bb.0: ; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = mem[2,3,2,3] -; X86-SSE2-NEXT: movd %xmm0, %eax +; X86-SSE2-NEXT: movl 8(%eax), %eax ; X86-SSE2-NEXT: retl ; -; X64-SSSE3-LABEL: t: -; X64-SSSE3: # %bb.0: -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = mem[2,3,2,3] -; X64-SSSE3-NEXT: movd %xmm0, %eax -; X64-SSSE3-NEXT: retq -; -; X64-AVX-LABEL: t: -; X64-AVX: # %bb.0: -; X64-AVX-NEXT: movl 8(%rdi), %eax -; X64-AVX-NEXT: retq +; X64-LABEL: t: +; X64: # %bb.0: +; X64-NEXT: movl 8(%rdi), %eax +; X64-NEXT: retq %tmp2 = load <2 x i64>, ptr %val, align 16 ; <<2 x i64>> [#uses=1] %tmp3 = bitcast <2 x i64> %tmp2 to <4 x i32> ; <<4 x i32>> [#uses=1] %tmp4 = extractelement <4 x i32> %tmp3, i32 2 ; [#uses=1] @@ -286,15 +279,14 @@ entry: define i32 @PR85419(ptr %p0) { ; X86-SSE2-LABEL: PR85419: ; X86-SSE2: # %bb.0: -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-SSE2-NEXT: movdqa (%eax), %xmm0 -; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,1,1] -; X86-SSE2-NEXT: movd %xmm1, %ecx -; X86-SSE2-NEXT: xorl %edx, %edx -; X86-SSE2-NEXT: orl (%eax), %ecx -; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; X86-SSE2-NEXT: movd %xmm0, %eax -; X86-SSE2-NEXT: cmovel %edx, %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movl (%ecx), %edx +; X86-SSE2-NEXT: xorl %eax, %eax +; X86-SSE2-NEXT: orl 4(%ecx), %edx +; X86-SSE2-NEXT: je .LBB8_2 +; X86-SSE2-NEXT: # %bb.1: +; X86-SSE2-NEXT: movl 8(%ecx), %eax +; X86-SSE2-NEXT: .LBB8_2: ; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: PR85419: @@ -443,35 +435,35 @@ define i32 @main() nounwind { ; X86-SSE2: # %bb.0: ; X86-SSE2-NEXT: pushl %ebp ; X86-SSE2-NEXT: movl %esp, %ebp +; X86-SSE2-NEXT: pushl %edi ; X86-SSE2-NEXT: pushl %esi ; X86-SSE2-NEXT: andl $-32, %esp ; X86-SSE2-NEXT: subl $64, %esp -; X86-SSE2-NEXT: movdqa zero, %xmm0 -; X86-SSE2-NEXT: movaps n1+16, %xmm1 -; X86-SSE2-NEXT: movaps n1, %xmm2 -; X86-SSE2-NEXT: movaps %xmm2, zero -; X86-SSE2-NEXT: movaps %xmm1, zero+16 -; X86-SSE2-NEXT: movaps {{.*#+}} xmm1 = [2,2,2,2] -; X86-SSE2-NEXT: movaps %xmm1, {{[0-9]+}}(%esp) -; X86-SSE2-NEXT: movaps %xmm1, (%esp) -; X86-SSE2-NEXT: movdqa (%esp), %xmm1 -; X86-SSE2-NEXT: movaps {{[0-9]+}}(%esp), %xmm2 -; X86-SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] -; X86-SSE2-NEXT: movd %xmm2, %eax -; X86-SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; X86-SSE2-NEXT: movd %xmm2, %ecx +; X86-SSE2-NEXT: movaps n1+16, %xmm0 +; X86-SSE2-NEXT: movaps n1, %xmm1 +; X86-SSE2-NEXT: movl zero+4, %ecx +; X86-SSE2-NEXT: movl zero+8, %eax +; X86-SSE2-NEXT: movaps %xmm1, zero +; X86-SSE2-NEXT: movaps %xmm0, zero+16 +; X86-SSE2-NEXT: movaps {{.*#+}} xmm0 = [2,2,2,2] +; X86-SSE2-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) +; X86-SSE2-NEXT: movaps %xmm0, (%esp) +; X86-SSE2-NEXT: movdqa (%esp), %xmm0 +; X86-SSE2-NEXT: movaps {{[0-9]+}}(%esp), %xmm1 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; X86-SSE2-NEXT: movd %xmm1, %esi ; X86-SSE2-NEXT: xorl %edx, %edx -; X86-SSE2-NEXT: divl %ecx -; X86-SSE2-NEXT: movl %eax, %ecx +; X86-SSE2-NEXT: divl %esi +; X86-SSE2-NEXT: movl %eax, %esi ; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X86-SSE2-NEXT: movd %xmm0, %eax -; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1] -; X86-SSE2-NEXT: movd %xmm0, %esi +; X86-SSE2-NEXT: movd %xmm0, %edi +; X86-SSE2-NEXT: movl %ecx, %eax ; X86-SSE2-NEXT: xorl %edx, %edx -; X86-SSE2-NEXT: divl %esi -; X86-SSE2-NEXT: addl %ecx, %eax -; X86-SSE2-NEXT: leal -4(%ebp), %esp +; X86-SSE2-NEXT: divl %edi +; X86-SSE2-NEXT: addl %esi, %eax +; X86-SSE2-NEXT: leal -8(%ebp), %esp ; X86-SSE2-NEXT: popl %esi +; X86-SSE2-NEXT: popl %edi ; X86-SSE2-NEXT: popl %ebp ; X86-SSE2-NEXT: retl ; @@ -481,31 +473,29 @@ define i32 @main() nounwind { ; X64-SSSE3-NEXT: movq %rsp, %rbp ; X64-SSSE3-NEXT: andq $-32, %rsp ; X64-SSSE3-NEXT: subq $64, %rsp -; X64-SSSE3-NEXT: movdqa zero(%rip), %xmm0 ; X64-SSSE3-NEXT: movq n1@GOTPCREL(%rip), %rax -; X64-SSSE3-NEXT: movaps (%rax), %xmm1 -; X64-SSSE3-NEXT: movaps 16(%rax), %xmm2 -; X64-SSSE3-NEXT: movaps %xmm1, zero(%rip) -; X64-SSSE3-NEXT: movaps %xmm2, zero+16(%rip) -; X64-SSSE3-NEXT: movaps {{.*#+}} xmm1 = [2,2,2,2] -; X64-SSSE3-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp) -; X64-SSSE3-NEXT: movaps %xmm1, (%rsp) -; X64-SSSE3-NEXT: movdqa (%rsp), %xmm1 -; X64-SSSE3-NEXT: movaps {{[0-9]+}}(%rsp), %xmm2 -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] -; X64-SSSE3-NEXT: movd %xmm2, %eax -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; X64-SSSE3-NEXT: movd %xmm2, %ecx +; X64-SSSE3-NEXT: movaps (%rax), %xmm0 +; X64-SSSE3-NEXT: movaps 16(%rax), %xmm1 +; X64-SSSE3-NEXT: movl zero+4(%rip), %ecx +; X64-SSSE3-NEXT: movl zero+8(%rip), %eax +; X64-SSSE3-NEXT: movaps %xmm0, zero(%rip) +; X64-SSSE3-NEXT: movaps %xmm1, zero+16(%rip) +; X64-SSSE3-NEXT: movaps {{.*#+}} xmm0 = [2,2,2,2] +; X64-SSSE3-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp) +; X64-SSSE3-NEXT: movaps %xmm0, (%rsp) +; X64-SSSE3-NEXT: movdqa (%rsp), %xmm0 +; X64-SSSE3-NEXT: movaps {{[0-9]+}}(%rsp), %xmm1 +; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; X64-SSSE3-NEXT: movd %xmm1, %esi ; X64-SSSE3-NEXT: xorl %edx, %edx -; X64-SSSE3-NEXT: divl %ecx -; X64-SSSE3-NEXT: movl %eax, %ecx +; X64-SSSE3-NEXT: divl %esi +; X64-SSSE3-NEXT: movl %eax, %esi ; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X64-SSSE3-NEXT: movd %xmm0, %eax -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1] -; X64-SSSE3-NEXT: movd %xmm0, %esi +; X64-SSSE3-NEXT: movd %xmm0, %edi +; X64-SSSE3-NEXT: movl %ecx, %eax ; X64-SSSE3-NEXT: xorl %edx, %edx -; X64-SSSE3-NEXT: divl %esi -; X64-SSSE3-NEXT: addl %ecx, %eax +; X64-SSSE3-NEXT: divl %edi +; X64-SSSE3-NEXT: addl %esi, %eax ; X64-SSSE3-NEXT: movq %rbp, %rsp ; X64-SSSE3-NEXT: popq %rbp ; X64-SSSE3-NEXT: retq diff --git a/llvm/test/CodeGen/X86/masked_store.ll b/llvm/test/CodeGen/X86/masked_store.ll index 03245ea31730..6aa0a81c9020 100644 --- a/llvm/test/CodeGen/X86/masked_store.ll +++ b/llvm/test/CodeGen/X86/masked_store.ll @@ -5638,479 +5638,247 @@ define void @PR11210(<4 x float> %x, ptr %ptr, <4 x float> %y, <2 x i64> %mask) } define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigger.ptr, ptr %val.ptr, ptr %dst) nounwind { -; SSE2-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: -; SSE2: ## %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm6 -; SSE2-NEXT: movdqa 32(%rdi), %xmm7 -; SSE2-NEXT: movdqa 64(%rdi), %xmm8 -; SSE2-NEXT: movl 80(%rsi), %eax -; SSE2-NEXT: movl 64(%rsi), %r8d -; SSE2-NEXT: movl 48(%rsi), %r9d -; SSE2-NEXT: movl 32(%rsi), %r10d -; SSE2-NEXT: movl 16(%rsi), %r11d -; SSE2-NEXT: movdqa 80(%rsi), %xmm0 -; SSE2-NEXT: movdqa 64(%rsi), %xmm1 -; SSE2-NEXT: movdqa 48(%rsi), %xmm2 -; SSE2-NEXT: movdqa 32(%rsi), %xmm3 -; SSE2-NEXT: movdqa 16(%rsi), %xmm4 -; SSE2-NEXT: movdqa (%rsi), %xmm5 -; SSE2-NEXT: packssdw 48(%rdi), %xmm7 -; SSE2-NEXT: packssdw 16(%rdi), %xmm6 -; SSE2-NEXT: packsswb %xmm7, %xmm6 -; SSE2-NEXT: packssdw 80(%rdi), %xmm8 -; SSE2-NEXT: packsswb %xmm8, %xmm8 -; SSE2-NEXT: pmovmskb %xmm6, %edi -; SSE2-NEXT: andl $21845, %edi ## imm = 0x5555 -; SSE2-NEXT: pmovmskb %xmm8, %ecx -; SSE2-NEXT: andl $85, %ecx -; SSE2-NEXT: shll $16, %ecx -; SSE2-NEXT: orl %edi, %ecx -; SSE2-NEXT: testb $1, %cl -; SSE2-NEXT: jne LBB31_1 -; SSE2-NEXT: ## %bb.2: ## %else -; SSE2-NEXT: testb $2, %cl -; SSE2-NEXT: jne LBB31_3 -; SSE2-NEXT: LBB31_4: ## %else2 -; SSE2-NEXT: testb $4, %cl -; SSE2-NEXT: jne LBB31_5 -; SSE2-NEXT: LBB31_6: ## %else4 -; SSE2-NEXT: testb $8, %cl -; SSE2-NEXT: jne LBB31_7 -; SSE2-NEXT: LBB31_8: ## %else6 -; SSE2-NEXT: testb $16, %cl -; SSE2-NEXT: jne LBB31_9 -; SSE2-NEXT: LBB31_10: ## %else8 -; SSE2-NEXT: testb $32, %cl -; SSE2-NEXT: jne LBB31_11 -; SSE2-NEXT: LBB31_12: ## %else10 -; SSE2-NEXT: testb $64, %cl -; SSE2-NEXT: jne LBB31_13 -; SSE2-NEXT: LBB31_14: ## %else12 -; SSE2-NEXT: testb %cl, %cl -; SSE2-NEXT: js LBB31_15 -; SSE2-NEXT: LBB31_16: ## %else14 -; SSE2-NEXT: testl $256, %ecx ## imm = 0x100 -; SSE2-NEXT: jne LBB31_17 -; SSE2-NEXT: LBB31_18: ## %else16 -; SSE2-NEXT: testl $512, %ecx ## imm = 0x200 -; SSE2-NEXT: jne LBB31_19 -; SSE2-NEXT: LBB31_20: ## %else18 -; SSE2-NEXT: testl $1024, %ecx ## imm = 0x400 -; SSE2-NEXT: jne LBB31_21 -; SSE2-NEXT: LBB31_22: ## %else20 -; SSE2-NEXT: testl $2048, %ecx ## imm = 0x800 -; SSE2-NEXT: jne LBB31_23 -; SSE2-NEXT: LBB31_24: ## %else22 -; SSE2-NEXT: testl $4096, %ecx ## imm = 0x1000 -; SSE2-NEXT: jne LBB31_25 -; SSE2-NEXT: LBB31_26: ## %else24 -; SSE2-NEXT: testl $8192, %ecx ## imm = 0x2000 -; SSE2-NEXT: jne LBB31_27 -; SSE2-NEXT: LBB31_28: ## %else26 -; SSE2-NEXT: testl $16384, %ecx ## imm = 0x4000 -; SSE2-NEXT: jne LBB31_29 -; SSE2-NEXT: LBB31_30: ## %else28 -; SSE2-NEXT: testw %cx, %cx -; SSE2-NEXT: js LBB31_31 -; SSE2-NEXT: LBB31_32: ## %else30 -; SSE2-NEXT: testl $65536, %ecx ## imm = 0x10000 -; SSE2-NEXT: jne LBB31_33 -; SSE2-NEXT: LBB31_34: ## %else32 -; SSE2-NEXT: testl $131072, %ecx ## imm = 0x20000 -; SSE2-NEXT: jne LBB31_35 -; SSE2-NEXT: LBB31_36: ## %else34 -; SSE2-NEXT: testl $262144, %ecx ## imm = 0x40000 -; SSE2-NEXT: jne LBB31_37 -; SSE2-NEXT: LBB31_38: ## %else36 -; SSE2-NEXT: testl $524288, %ecx ## imm = 0x80000 -; SSE2-NEXT: jne LBB31_39 -; SSE2-NEXT: LBB31_40: ## %else38 -; SSE2-NEXT: testl $1048576, %ecx ## imm = 0x100000 -; SSE2-NEXT: jne LBB31_41 -; SSE2-NEXT: LBB31_42: ## %else40 -; SSE2-NEXT: testl $2097152, %ecx ## imm = 0x200000 -; SSE2-NEXT: jne LBB31_43 -; SSE2-NEXT: LBB31_44: ## %else42 -; SSE2-NEXT: testl $4194304, %ecx ## imm = 0x400000 -; SSE2-NEXT: je LBB31_46 -; SSE2-NEXT: LBB31_45: ## %cond.store43 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] -; SSE2-NEXT: movd %xmm1, %eax -; SSE2-NEXT: movl %eax, 88(%rdx) -; SSE2-NEXT: LBB31_46: ## %else44 -; SSE2-NEXT: movb $1, %al -; SSE2-NEXT: testb %al, %al -; SSE2-NEXT: jne LBB31_48 -; SSE2-NEXT: ## %bb.47: ## %cond.store45 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[3,3,3,3] -; SSE2-NEXT: movd %xmm0, %eax -; SSE2-NEXT: movl %eax, 92(%rdx) -; SSE2-NEXT: LBB31_48: ## %else46 -; SSE2-NEXT: retq -; SSE2-NEXT: LBB31_1: ## %cond.store -; SSE2-NEXT: movl (%rsi), %esi -; SSE2-NEXT: movl %esi, (%rdx) -; SSE2-NEXT: testb $2, %cl -; SSE2-NEXT: je LBB31_4 -; SSE2-NEXT: LBB31_3: ## %cond.store1 -; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm5[1,1,1,1] -; SSE2-NEXT: movd %xmm6, %esi -; SSE2-NEXT: movl %esi, 4(%rdx) -; SSE2-NEXT: testb $4, %cl -; SSE2-NEXT: je LBB31_6 -; SSE2-NEXT: LBB31_5: ## %cond.store3 -; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm5[2,3,2,3] -; SSE2-NEXT: movd %xmm6, %esi -; SSE2-NEXT: movl %esi, 8(%rdx) -; SSE2-NEXT: testb $8, %cl -; SSE2-NEXT: je LBB31_8 -; SSE2-NEXT: LBB31_7: ## %cond.store5 -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm5[3,3,3,3] -; SSE2-NEXT: movd %xmm5, %esi -; SSE2-NEXT: movl %esi, 12(%rdx) -; SSE2-NEXT: testb $16, %cl -; SSE2-NEXT: je LBB31_10 -; SSE2-NEXT: LBB31_9: ## %cond.store7 -; SSE2-NEXT: movl %r11d, 16(%rdx) -; SSE2-NEXT: testb $32, %cl -; SSE2-NEXT: je LBB31_12 -; SSE2-NEXT: LBB31_11: ## %cond.store9 -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[1,1,1,1] -; SSE2-NEXT: movd %xmm5, %esi -; SSE2-NEXT: movl %esi, 20(%rdx) -; SSE2-NEXT: testb $64, %cl -; SSE2-NEXT: je LBB31_14 -; SSE2-NEXT: LBB31_13: ## %cond.store11 -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[2,3,2,3] -; SSE2-NEXT: movd %xmm5, %esi -; SSE2-NEXT: movl %esi, 24(%rdx) -; SSE2-NEXT: testb %cl, %cl -; SSE2-NEXT: jns LBB31_16 -; SSE2-NEXT: LBB31_15: ## %cond.store13 -; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm4[3,3,3,3] -; SSE2-NEXT: movd %xmm4, %esi -; SSE2-NEXT: movl %esi, 28(%rdx) -; SSE2-NEXT: testl $256, %ecx ## imm = 0x100 -; SSE2-NEXT: je LBB31_18 -; SSE2-NEXT: LBB31_17: ## %cond.store15 -; SSE2-NEXT: movl %r10d, 32(%rdx) -; SSE2-NEXT: testl $512, %ecx ## imm = 0x200 -; SSE2-NEXT: je LBB31_20 -; SSE2-NEXT: LBB31_19: ## %cond.store17 -; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm3[1,1,1,1] -; SSE2-NEXT: movd %xmm4, %esi -; SSE2-NEXT: movl %esi, 36(%rdx) -; SSE2-NEXT: testl $1024, %ecx ## imm = 0x400 -; SSE2-NEXT: je LBB31_22 -; SSE2-NEXT: LBB31_21: ## %cond.store19 -; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm3[2,3,2,3] -; SSE2-NEXT: movd %xmm4, %esi -; SSE2-NEXT: movl %esi, 40(%rdx) -; SSE2-NEXT: testl $2048, %ecx ## imm = 0x800 -; SSE2-NEXT: je LBB31_24 -; SSE2-NEXT: LBB31_23: ## %cond.store21 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm3[3,3,3,3] -; SSE2-NEXT: movd %xmm3, %esi -; SSE2-NEXT: movl %esi, 44(%rdx) -; SSE2-NEXT: testl $4096, %ecx ## imm = 0x1000 -; SSE2-NEXT: je LBB31_26 -; SSE2-NEXT: LBB31_25: ## %cond.store23 -; SSE2-NEXT: movl %r9d, 48(%rdx) -; SSE2-NEXT: testl $8192, %ecx ## imm = 0x2000 -; SSE2-NEXT: je LBB31_28 -; SSE2-NEXT: LBB31_27: ## %cond.store25 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[1,1,1,1] -; SSE2-NEXT: movd %xmm3, %esi -; SSE2-NEXT: movl %esi, 52(%rdx) -; SSE2-NEXT: testl $16384, %ecx ## imm = 0x4000 -; SSE2-NEXT: je LBB31_30 -; SSE2-NEXT: LBB31_29: ## %cond.store27 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] -; SSE2-NEXT: movd %xmm3, %esi -; SSE2-NEXT: movl %esi, 56(%rdx) -; SSE2-NEXT: testw %cx, %cx -; SSE2-NEXT: jns LBB31_32 -; SSE2-NEXT: LBB31_31: ## %cond.store29 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[3,3,3,3] -; SSE2-NEXT: movd %xmm2, %esi -; SSE2-NEXT: movl %esi, 60(%rdx) -; SSE2-NEXT: testl $65536, %ecx ## imm = 0x10000 -; SSE2-NEXT: je LBB31_34 -; SSE2-NEXT: LBB31_33: ## %cond.store31 -; SSE2-NEXT: movl %r8d, 64(%rdx) -; SSE2-NEXT: testl $131072, %ecx ## imm = 0x20000 -; SSE2-NEXT: je LBB31_36 -; SSE2-NEXT: LBB31_35: ## %cond.store33 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,1,1] -; SSE2-NEXT: movd %xmm2, %esi -; SSE2-NEXT: movl %esi, 68(%rdx) -; SSE2-NEXT: testl $262144, %ecx ## imm = 0x40000 -; SSE2-NEXT: je LBB31_38 -; SSE2-NEXT: LBB31_37: ## %cond.store35 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; SSE2-NEXT: movd %xmm2, %esi -; SSE2-NEXT: movl %esi, 72(%rdx) -; SSE2-NEXT: testl $524288, %ecx ## imm = 0x80000 -; SSE2-NEXT: je LBB31_40 -; SSE2-NEXT: LBB31_39: ## %cond.store37 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[3,3,3,3] -; SSE2-NEXT: movd %xmm1, %esi -; SSE2-NEXT: movl %esi, 76(%rdx) -; SSE2-NEXT: testl $1048576, %ecx ## imm = 0x100000 -; SSE2-NEXT: je LBB31_42 -; SSE2-NEXT: LBB31_41: ## %cond.store39 -; SSE2-NEXT: movl %eax, 80(%rdx) -; SSE2-NEXT: testl $2097152, %ecx ## imm = 0x200000 -; SSE2-NEXT: je LBB31_44 -; SSE2-NEXT: LBB31_43: ## %cond.store41 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,1,1] -; SSE2-NEXT: movd %xmm1, %eax -; SSE2-NEXT: movl %eax, 84(%rdx) -; SSE2-NEXT: testl $4194304, %ecx ## imm = 0x400000 -; SSE2-NEXT: jne LBB31_45 -; SSE2-NEXT: jmp LBB31_46 -; -; SSE4-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: -; SSE4: ## %bb.0: -; SSE4-NEXT: pushq %rbp -; SSE4-NEXT: pushq %r15 -; SSE4-NEXT: pushq %r14 -; SSE4-NEXT: pushq %r13 -; SSE4-NEXT: pushq %r12 -; SSE4-NEXT: pushq %rbx -; SSE4-NEXT: movdqa (%rdi), %xmm1 -; SSE4-NEXT: movdqa 32(%rdi), %xmm2 -; SSE4-NEXT: movdqa 64(%rdi), %xmm0 -; SSE4-NEXT: movl 92(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 88(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 84(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 80(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 76(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 72(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 68(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 64(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 60(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 56(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 52(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: packssdw 48(%rdi), %xmm2 -; SSE4-NEXT: packssdw 16(%rdi), %xmm1 -; SSE4-NEXT: packsswb %xmm2, %xmm1 -; SSE4-NEXT: packssdw 80(%rdi), %xmm0 -; SSE4-NEXT: packsswb %xmm0, %xmm0 -; SSE4-NEXT: pmovmskb %xmm1, %eax -; SSE4-NEXT: andl $21845, %eax ## imm = 0x5555 -; SSE4-NEXT: pmovmskb %xmm0, %edi -; SSE4-NEXT: andl $85, %edi -; SSE4-NEXT: shll $16, %edi -; SSE4-NEXT: orl %eax, %edi -; SSE4-NEXT: movl 48(%rsi), %r13d -; SSE4-NEXT: testb $1, %dil -; SSE4-NEXT: movl 44(%rsi), %eax -; SSE4-NEXT: movl 40(%rsi), %ecx -; SSE4-NEXT: movl 36(%rsi), %r8d -; SSE4-NEXT: movl 32(%rsi), %r9d -; SSE4-NEXT: movl 28(%rsi), %r10d -; SSE4-NEXT: movl 24(%rsi), %r11d -; SSE4-NEXT: movl 20(%rsi), %ebx -; SSE4-NEXT: movl 16(%rsi), %ebp -; SSE4-NEXT: movl 12(%rsi), %r14d -; SSE4-NEXT: movl 8(%rsi), %r15d -; SSE4-NEXT: movl 4(%rsi), %r12d -; SSE4-NEXT: jne LBB31_1 -; SSE4-NEXT: ## %bb.2: ## %else -; SSE4-NEXT: testb $2, %dil -; SSE4-NEXT: jne LBB31_3 -; SSE4-NEXT: LBB31_4: ## %else2 -; SSE4-NEXT: testb $4, %dil -; SSE4-NEXT: jne LBB31_5 -; SSE4-NEXT: LBB31_6: ## %else4 -; SSE4-NEXT: testb $8, %dil -; SSE4-NEXT: jne LBB31_7 -; SSE4-NEXT: LBB31_8: ## %else6 -; SSE4-NEXT: testb $16, %dil -; SSE4-NEXT: jne LBB31_9 -; SSE4-NEXT: LBB31_10: ## %else8 -; SSE4-NEXT: testb $32, %dil -; SSE4-NEXT: jne LBB31_11 -; SSE4-NEXT: LBB31_12: ## %else10 -; SSE4-NEXT: testb $64, %dil -; SSE4-NEXT: jne LBB31_13 -; SSE4-NEXT: LBB31_14: ## %else12 -; SSE4-NEXT: testb %dil, %dil -; SSE4-NEXT: js LBB31_15 -; SSE4-NEXT: LBB31_16: ## %else14 -; SSE4-NEXT: testl $256, %edi ## imm = 0x100 -; SSE4-NEXT: jne LBB31_17 -; SSE4-NEXT: LBB31_18: ## %else16 -; SSE4-NEXT: testl $512, %edi ## imm = 0x200 -; SSE4-NEXT: jne LBB31_19 -; SSE4-NEXT: LBB31_20: ## %else18 -; SSE4-NEXT: testl $1024, %edi ## imm = 0x400 -; SSE4-NEXT: jne LBB31_21 -; SSE4-NEXT: LBB31_22: ## %else20 -; SSE4-NEXT: testl $2048, %edi ## imm = 0x800 -; SSE4-NEXT: jne LBB31_23 -; SSE4-NEXT: LBB31_24: ## %else22 -; SSE4-NEXT: testl $4096, %edi ## imm = 0x1000 -; SSE4-NEXT: jne LBB31_25 -; SSE4-NEXT: LBB31_26: ## %else24 -; SSE4-NEXT: testl $8192, %edi ## imm = 0x2000 -; SSE4-NEXT: jne LBB31_27 -; SSE4-NEXT: LBB31_28: ## %else26 -; SSE4-NEXT: testl $16384, %edi ## imm = 0x4000 -; SSE4-NEXT: jne LBB31_29 -; SSE4-NEXT: LBB31_30: ## %else28 -; SSE4-NEXT: testw %di, %di -; SSE4-NEXT: js LBB31_31 -; SSE4-NEXT: LBB31_32: ## %else30 -; SSE4-NEXT: testl $65536, %edi ## imm = 0x10000 -; SSE4-NEXT: jne LBB31_33 -; SSE4-NEXT: LBB31_34: ## %else32 -; SSE4-NEXT: testl $131072, %edi ## imm = 0x20000 -; SSE4-NEXT: jne LBB31_35 -; SSE4-NEXT: LBB31_36: ## %else34 -; SSE4-NEXT: testl $262144, %edi ## imm = 0x40000 -; SSE4-NEXT: jne LBB31_37 -; SSE4-NEXT: LBB31_38: ## %else36 -; SSE4-NEXT: testl $524288, %edi ## imm = 0x80000 -; SSE4-NEXT: jne LBB31_39 -; SSE4-NEXT: LBB31_40: ## %else38 -; SSE4-NEXT: testl $1048576, %edi ## imm = 0x100000 -; SSE4-NEXT: jne LBB31_41 -; SSE4-NEXT: LBB31_42: ## %else40 -; SSE4-NEXT: testl $2097152, %edi ## imm = 0x200000 -; SSE4-NEXT: jne LBB31_43 -; SSE4-NEXT: LBB31_44: ## %else42 -; SSE4-NEXT: testl $4194304, %edi ## imm = 0x400000 -; SSE4-NEXT: je LBB31_46 -; SSE4-NEXT: LBB31_45: ## %cond.store43 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 88(%rdx) -; SSE4-NEXT: LBB31_46: ## %else44 -; SSE4-NEXT: movb $1, %al -; SSE4-NEXT: testb %al, %al -; SSE4-NEXT: jne LBB31_48 -; SSE4-NEXT: ## %bb.47: ## %cond.store45 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 92(%rdx) -; SSE4-NEXT: LBB31_48: ## %else46 -; SSE4-NEXT: popq %rbx -; SSE4-NEXT: popq %r12 -; SSE4-NEXT: popq %r13 -; SSE4-NEXT: popq %r14 -; SSE4-NEXT: popq %r15 -; SSE4-NEXT: popq %rbp -; SSE4-NEXT: retq -; SSE4-NEXT: LBB31_1: ## %cond.store -; SSE4-NEXT: movl (%rsi), %esi -; SSE4-NEXT: movl %esi, (%rdx) -; SSE4-NEXT: testb $2, %dil -; SSE4-NEXT: je LBB31_4 -; SSE4-NEXT: LBB31_3: ## %cond.store1 -; SSE4-NEXT: movl %r12d, 4(%rdx) -; SSE4-NEXT: testb $4, %dil -; SSE4-NEXT: je LBB31_6 -; SSE4-NEXT: LBB31_5: ## %cond.store3 -; SSE4-NEXT: movl %r15d, 8(%rdx) -; SSE4-NEXT: testb $8, %dil -; SSE4-NEXT: je LBB31_8 -; SSE4-NEXT: LBB31_7: ## %cond.store5 -; SSE4-NEXT: movl %r14d, 12(%rdx) -; SSE4-NEXT: testb $16, %dil -; SSE4-NEXT: je LBB31_10 -; SSE4-NEXT: LBB31_9: ## %cond.store7 -; SSE4-NEXT: movl %ebp, 16(%rdx) -; SSE4-NEXT: testb $32, %dil -; SSE4-NEXT: je LBB31_12 -; SSE4-NEXT: LBB31_11: ## %cond.store9 -; SSE4-NEXT: movl %ebx, 20(%rdx) -; SSE4-NEXT: testb $64, %dil -; SSE4-NEXT: je LBB31_14 -; SSE4-NEXT: LBB31_13: ## %cond.store11 -; SSE4-NEXT: movl %r11d, 24(%rdx) -; SSE4-NEXT: testb %dil, %dil -; SSE4-NEXT: jns LBB31_16 -; SSE4-NEXT: LBB31_15: ## %cond.store13 -; SSE4-NEXT: movl %r10d, 28(%rdx) -; SSE4-NEXT: testl $256, %edi ## imm = 0x100 -; SSE4-NEXT: je LBB31_18 -; SSE4-NEXT: LBB31_17: ## %cond.store15 -; SSE4-NEXT: movl %r9d, 32(%rdx) -; SSE4-NEXT: testl $512, %edi ## imm = 0x200 -; SSE4-NEXT: je LBB31_20 -; SSE4-NEXT: LBB31_19: ## %cond.store17 -; SSE4-NEXT: movl %r8d, 36(%rdx) -; SSE4-NEXT: testl $1024, %edi ## imm = 0x400 -; SSE4-NEXT: je LBB31_22 -; SSE4-NEXT: LBB31_21: ## %cond.store19 -; SSE4-NEXT: movl %ecx, 40(%rdx) -; SSE4-NEXT: testl $2048, %edi ## imm = 0x800 -; SSE4-NEXT: je LBB31_24 -; SSE4-NEXT: LBB31_23: ## %cond.store21 -; SSE4-NEXT: movl %eax, 44(%rdx) -; SSE4-NEXT: testl $4096, %edi ## imm = 0x1000 -; SSE4-NEXT: je LBB31_26 -; SSE4-NEXT: LBB31_25: ## %cond.store23 -; SSE4-NEXT: movl %r13d, 48(%rdx) -; SSE4-NEXT: testl $8192, %edi ## imm = 0x2000 -; SSE4-NEXT: je LBB31_28 -; SSE4-NEXT: LBB31_27: ## %cond.store25 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 52(%rdx) -; SSE4-NEXT: testl $16384, %edi ## imm = 0x4000 -; SSE4-NEXT: je LBB31_30 -; SSE4-NEXT: LBB31_29: ## %cond.store27 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 56(%rdx) -; SSE4-NEXT: testw %di, %di -; SSE4-NEXT: jns LBB31_32 -; SSE4-NEXT: LBB31_31: ## %cond.store29 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 60(%rdx) -; SSE4-NEXT: testl $65536, %edi ## imm = 0x10000 -; SSE4-NEXT: je LBB31_34 -; SSE4-NEXT: LBB31_33: ## %cond.store31 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 64(%rdx) -; SSE4-NEXT: testl $131072, %edi ## imm = 0x20000 -; SSE4-NEXT: je LBB31_36 -; SSE4-NEXT: LBB31_35: ## %cond.store33 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 68(%rdx) -; SSE4-NEXT: testl $262144, %edi ## imm = 0x40000 -; SSE4-NEXT: je LBB31_38 -; SSE4-NEXT: LBB31_37: ## %cond.store35 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 72(%rdx) -; SSE4-NEXT: testl $524288, %edi ## imm = 0x80000 -; SSE4-NEXT: je LBB31_40 -; SSE4-NEXT: LBB31_39: ## %cond.store37 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 76(%rdx) -; SSE4-NEXT: testl $1048576, %edi ## imm = 0x100000 -; SSE4-NEXT: je LBB31_42 -; SSE4-NEXT: LBB31_41: ## %cond.store39 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 80(%rdx) -; SSE4-NEXT: testl $2097152, %edi ## imm = 0x200000 -; SSE4-NEXT: je LBB31_44 -; SSE4-NEXT: LBB31_43: ## %cond.store41 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 84(%rdx) -; SSE4-NEXT: testl $4194304, %edi ## imm = 0x400000 -; SSE4-NEXT: jne LBB31_45 -; SSE4-NEXT: jmp LBB31_46 +; SSE-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: +; SSE: ## %bb.0: +; SSE-NEXT: pushq %rbp +; SSE-NEXT: pushq %r15 +; SSE-NEXT: pushq %r14 +; SSE-NEXT: pushq %r13 +; SSE-NEXT: pushq %r12 +; SSE-NEXT: pushq %rbx +; SSE-NEXT: movdqa (%rdi), %xmm1 +; SSE-NEXT: movdqa 32(%rdi), %xmm2 +; SSE-NEXT: movdqa 64(%rdi), %xmm0 +; SSE-NEXT: movl 92(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 88(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 84(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 80(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 76(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 72(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 68(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 64(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 60(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 56(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 52(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: packssdw 48(%rdi), %xmm2 +; SSE-NEXT: packssdw 16(%rdi), %xmm1 +; SSE-NEXT: packsswb %xmm2, %xmm1 +; SSE-NEXT: packssdw 80(%rdi), %xmm0 +; SSE-NEXT: packsswb %xmm0, %xmm0 +; SSE-NEXT: pmovmskb %xmm1, %eax +; SSE-NEXT: andl $21845, %eax ## imm = 0x5555 +; SSE-NEXT: pmovmskb %xmm0, %edi +; SSE-NEXT: andl $85, %edi +; SSE-NEXT: shll $16, %edi +; SSE-NEXT: orl %eax, %edi +; SSE-NEXT: movl 48(%rsi), %r13d +; SSE-NEXT: testb $1, %dil +; SSE-NEXT: movl 44(%rsi), %eax +; SSE-NEXT: movl 40(%rsi), %ecx +; SSE-NEXT: movl 36(%rsi), %r8d +; SSE-NEXT: movl 32(%rsi), %r9d +; SSE-NEXT: movl 28(%rsi), %r10d +; SSE-NEXT: movl 24(%rsi), %r11d +; SSE-NEXT: movl 20(%rsi), %ebx +; SSE-NEXT: movl 16(%rsi), %ebp +; SSE-NEXT: movl 12(%rsi), %r14d +; SSE-NEXT: movl 8(%rsi), %r15d +; SSE-NEXT: movl 4(%rsi), %r12d +; SSE-NEXT: jne LBB31_1 +; SSE-NEXT: ## %bb.2: ## %else +; SSE-NEXT: testb $2, %dil +; SSE-NEXT: jne LBB31_3 +; SSE-NEXT: LBB31_4: ## %else2 +; SSE-NEXT: testb $4, %dil +; SSE-NEXT: jne LBB31_5 +; SSE-NEXT: LBB31_6: ## %else4 +; SSE-NEXT: testb $8, %dil +; SSE-NEXT: jne LBB31_7 +; SSE-NEXT: LBB31_8: ## %else6 +; SSE-NEXT: testb $16, %dil +; SSE-NEXT: jne LBB31_9 +; SSE-NEXT: LBB31_10: ## %else8 +; SSE-NEXT: testb $32, %dil +; SSE-NEXT: jne LBB31_11 +; SSE-NEXT: LBB31_12: ## %else10 +; SSE-NEXT: testb $64, %dil +; SSE-NEXT: jne LBB31_13 +; SSE-NEXT: LBB31_14: ## %else12 +; SSE-NEXT: testb %dil, %dil +; SSE-NEXT: js LBB31_15 +; SSE-NEXT: LBB31_16: ## %else14 +; SSE-NEXT: testl $256, %edi ## imm = 0x100 +; SSE-NEXT: jne LBB31_17 +; SSE-NEXT: LBB31_18: ## %else16 +; SSE-NEXT: testl $512, %edi ## imm = 0x200 +; SSE-NEXT: jne LBB31_19 +; SSE-NEXT: LBB31_20: ## %else18 +; SSE-NEXT: testl $1024, %edi ## imm = 0x400 +; SSE-NEXT: jne LBB31_21 +; SSE-NEXT: LBB31_22: ## %else20 +; SSE-NEXT: testl $2048, %edi ## imm = 0x800 +; SSE-NEXT: jne LBB31_23 +; SSE-NEXT: LBB31_24: ## %else22 +; SSE-NEXT: testl $4096, %edi ## imm = 0x1000 +; SSE-NEXT: jne LBB31_25 +; SSE-NEXT: LBB31_26: ## %else24 +; SSE-NEXT: testl $8192, %edi ## imm = 0x2000 +; SSE-NEXT: jne LBB31_27 +; SSE-NEXT: LBB31_28: ## %else26 +; SSE-NEXT: testl $16384, %edi ## imm = 0x4000 +; SSE-NEXT: jne LBB31_29 +; SSE-NEXT: LBB31_30: ## %else28 +; SSE-NEXT: testw %di, %di +; SSE-NEXT: js LBB31_31 +; SSE-NEXT: LBB31_32: ## %else30 +; SSE-NEXT: testl $65536, %edi ## imm = 0x10000 +; SSE-NEXT: jne LBB31_33 +; SSE-NEXT: LBB31_34: ## %else32 +; SSE-NEXT: testl $131072, %edi ## imm = 0x20000 +; SSE-NEXT: jne LBB31_35 +; SSE-NEXT: LBB31_36: ## %else34 +; SSE-NEXT: testl $262144, %edi ## imm = 0x40000 +; SSE-NEXT: jne LBB31_37 +; SSE-NEXT: LBB31_38: ## %else36 +; SSE-NEXT: testl $524288, %edi ## imm = 0x80000 +; SSE-NEXT: jne LBB31_39 +; SSE-NEXT: LBB31_40: ## %else38 +; SSE-NEXT: testl $1048576, %edi ## imm = 0x100000 +; SSE-NEXT: jne LBB31_41 +; SSE-NEXT: LBB31_42: ## %else40 +; SSE-NEXT: testl $2097152, %edi ## imm = 0x200000 +; SSE-NEXT: jne LBB31_43 +; SSE-NEXT: LBB31_44: ## %else42 +; SSE-NEXT: testl $4194304, %edi ## imm = 0x400000 +; SSE-NEXT: je LBB31_46 +; SSE-NEXT: LBB31_45: ## %cond.store43 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 88(%rdx) +; SSE-NEXT: LBB31_46: ## %else44 +; SSE-NEXT: movb $1, %al +; SSE-NEXT: testb %al, %al +; SSE-NEXT: jne LBB31_48 +; SSE-NEXT: ## %bb.47: ## %cond.store45 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 92(%rdx) +; SSE-NEXT: LBB31_48: ## %else46 +; SSE-NEXT: popq %rbx +; SSE-NEXT: popq %r12 +; SSE-NEXT: popq %r13 +; SSE-NEXT: popq %r14 +; SSE-NEXT: popq %r15 +; SSE-NEXT: popq %rbp +; SSE-NEXT: retq +; SSE-NEXT: LBB31_1: ## %cond.store +; SSE-NEXT: movl (%rsi), %esi +; SSE-NEXT: movl %esi, (%rdx) +; SSE-NEXT: testb $2, %dil +; SSE-NEXT: je LBB31_4 +; SSE-NEXT: LBB31_3: ## %cond.store1 +; SSE-NEXT: movl %r12d, 4(%rdx) +; SSE-NEXT: testb $4, %dil +; SSE-NEXT: je LBB31_6 +; SSE-NEXT: LBB31_5: ## %cond.store3 +; SSE-NEXT: movl %r15d, 8(%rdx) +; SSE-NEXT: testb $8, %dil +; SSE-NEXT: je LBB31_8 +; SSE-NEXT: LBB31_7: ## %cond.store5 +; SSE-NEXT: movl %r14d, 12(%rdx) +; SSE-NEXT: testb $16, %dil +; SSE-NEXT: je LBB31_10 +; SSE-NEXT: LBB31_9: ## %cond.store7 +; SSE-NEXT: movl %ebp, 16(%rdx) +; SSE-NEXT: testb $32, %dil +; SSE-NEXT: je LBB31_12 +; SSE-NEXT: LBB31_11: ## %cond.store9 +; SSE-NEXT: movl %ebx, 20(%rdx) +; SSE-NEXT: testb $64, %dil +; SSE-NEXT: je LBB31_14 +; SSE-NEXT: LBB31_13: ## %cond.store11 +; SSE-NEXT: movl %r11d, 24(%rdx) +; SSE-NEXT: testb %dil, %dil +; SSE-NEXT: jns LBB31_16 +; SSE-NEXT: LBB31_15: ## %cond.store13 +; SSE-NEXT: movl %r10d, 28(%rdx) +; SSE-NEXT: testl $256, %edi ## imm = 0x100 +; SSE-NEXT: je LBB31_18 +; SSE-NEXT: LBB31_17: ## %cond.store15 +; SSE-NEXT: movl %r9d, 32(%rdx) +; SSE-NEXT: testl $512, %edi ## imm = 0x200 +; SSE-NEXT: je LBB31_20 +; SSE-NEXT: LBB31_19: ## %cond.store17 +; SSE-NEXT: movl %r8d, 36(%rdx) +; SSE-NEXT: testl $1024, %edi ## imm = 0x400 +; SSE-NEXT: je LBB31_22 +; SSE-NEXT: LBB31_21: ## %cond.store19 +; SSE-NEXT: movl %ecx, 40(%rdx) +; SSE-NEXT: testl $2048, %edi ## imm = 0x800 +; SSE-NEXT: je LBB31_24 +; SSE-NEXT: LBB31_23: ## %cond.store21 +; SSE-NEXT: movl %eax, 44(%rdx) +; SSE-NEXT: testl $4096, %edi ## imm = 0x1000 +; SSE-NEXT: je LBB31_26 +; SSE-NEXT: LBB31_25: ## %cond.store23 +; SSE-NEXT: movl %r13d, 48(%rdx) +; SSE-NEXT: testl $8192, %edi ## imm = 0x2000 +; SSE-NEXT: je LBB31_28 +; SSE-NEXT: LBB31_27: ## %cond.store25 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 52(%rdx) +; SSE-NEXT: testl $16384, %edi ## imm = 0x4000 +; SSE-NEXT: je LBB31_30 +; SSE-NEXT: LBB31_29: ## %cond.store27 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 56(%rdx) +; SSE-NEXT: testw %di, %di +; SSE-NEXT: jns LBB31_32 +; SSE-NEXT: LBB31_31: ## %cond.store29 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 60(%rdx) +; SSE-NEXT: testl $65536, %edi ## imm = 0x10000 +; SSE-NEXT: je LBB31_34 +; SSE-NEXT: LBB31_33: ## %cond.store31 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 64(%rdx) +; SSE-NEXT: testl $131072, %edi ## imm = 0x20000 +; SSE-NEXT: je LBB31_36 +; SSE-NEXT: LBB31_35: ## %cond.store33 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 68(%rdx) +; SSE-NEXT: testl $262144, %edi ## imm = 0x40000 +; SSE-NEXT: je LBB31_38 +; SSE-NEXT: LBB31_37: ## %cond.store35 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 72(%rdx) +; SSE-NEXT: testl $524288, %edi ## imm = 0x80000 +; SSE-NEXT: je LBB31_40 +; SSE-NEXT: LBB31_39: ## %cond.store37 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 76(%rdx) +; SSE-NEXT: testl $1048576, %edi ## imm = 0x100000 +; SSE-NEXT: je LBB31_42 +; SSE-NEXT: LBB31_41: ## %cond.store39 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 80(%rdx) +; SSE-NEXT: testl $2097152, %edi ## imm = 0x200000 +; SSE-NEXT: je LBB31_44 +; SSE-NEXT: LBB31_43: ## %cond.store41 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 84(%rdx) +; SSE-NEXT: testl $4194304, %edi ## imm = 0x400000 +; SSE-NEXT: jne LBB31_45 +; SSE-NEXT: jmp LBB31_46 ; ; AVX1-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: ; AVX1: ## %bb.0: diff --git a/llvm/test/CodeGen/X86/shrink_vmul.ll b/llvm/test/CodeGen/X86/shrink_vmul.ll index 2610f4322c8e..62051d170994 100644 --- a/llvm/test/CodeGen/X86/shrink_vmul.ll +++ b/llvm/test/CodeGen/X86/shrink_vmul.ll @@ -1983,91 +1983,75 @@ define void @PR34947(ptr %p0, ptr %p1) nounwind { ; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-SSE-NEXT: movzwl 16(%eax), %edx ; X86-SSE-NEXT: movl %edx, (%esp) # 4-byte Spill -; X86-SSE-NEXT: movdqa (%eax), %xmm3 -; X86-SSE-NEXT: movdqa (%ecx), %xmm0 -; X86-SSE-NEXT: movdqa 16(%ecx), %xmm1 -; X86-SSE-NEXT: pxor %xmm5, %xmm5 -; X86-SSE-NEXT: movdqa %xmm3, %xmm2 -; X86-SSE-NEXT: pextrw $7, %xmm3, %eax -; X86-SSE-NEXT: pextrw $4, %xmm3, %edi -; X86-SSE-NEXT: pextrw $0, %xmm3, %ebp -; X86-SSE-NEXT: pextrw $1, %xmm3, %esi -; X86-SSE-NEXT: pextrw $3, %xmm3, %ebx -; X86-SSE-NEXT: movdqa %xmm3, %xmm4 -; X86-SSE-NEXT: punpcklwd {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3] -; X86-SSE-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm5[4],xmm2[5],xmm5[5],xmm2[6],xmm5[6],xmm2[7],xmm5[7] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm1[3,3,3,3] -; X86-SSE-NEXT: movd %xmm3, %ecx +; X86-SSE-NEXT: movdqa (%eax), %xmm2 +; X86-SSE-NEXT: pxor %xmm1, %xmm1 +; X86-SSE-NEXT: movdqa %xmm2, %xmm0 +; X86-SSE-NEXT: pextrw $7, %xmm2, %eax +; X86-SSE-NEXT: pextrw $4, %xmm2, %esi +; X86-SSE-NEXT: pextrw $1, %xmm2, %edi +; X86-SSE-NEXT: pextrw $0, %xmm2, %ebx +; X86-SSE-NEXT: pextrw $3, %xmm2, %ebp +; X86-SSE-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3] +; X86-SSE-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; X86-SSE-NEXT: xorl %edx, %edx +; X86-SSE-NEXT: divl 28(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm1 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm0[2,3,2,3] +; X86-SSE-NEXT: movd %xmm3, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx +; X86-SSE-NEXT: divl 24(%ecx) ; X86-SSE-NEXT: movd %edx, %xmm3 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm2[2,3,2,3] -; X86-SSE-NEXT: movd %xmm5, %eax -; X86-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] -; X86-SSE-NEXT: movd %xmm5, %ecx +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] +; X86-SSE-NEXT: movl %esi, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm5 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm3[0],xmm5[1],xmm3[1] +; X86-SSE-NEXT: divl 16(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm1 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X86-SSE-NEXT: movd %xmm0, %eax +; X86-SSE-NEXT: xorl %edx, %edx +; X86-SSE-NEXT: divl 20(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm0 +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] ; X86-SSE-NEXT: movl %edi, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-SSE-NEXT: divl 16(%edi) +; X86-SSE-NEXT: divl 4(%ecx) ; X86-SSE-NEXT: movd %edx, %xmm3 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,1,1] -; X86-SSE-NEXT: movd %xmm2, %eax -; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,1,1] -; X86-SSE-NEXT: movd %xmm1, %ecx +; X86-SSE-NEXT: movl %ebx, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm1 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] -; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm5[0] +; X86-SSE-NEXT: divl (%ecx) +; X86-SSE-NEXT: movd %edx, %xmm0 +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] ; X86-SSE-NEXT: movl %ebp, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl (%edi) -; X86-SSE-NEXT: movd %edx, %xmm1 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,1,1] -; X86-SSE-NEXT: movd %xmm2, %ecx -; X86-SSE-NEXT: movl %esi, %eax -; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm2 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[3,3,3,3] -; X86-SSE-NEXT: movd %xmm2, %ecx -; X86-SSE-NEXT: movl %ebx, %eax +; X86-SSE-NEXT: divl 12(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm3 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; X86-SSE-NEXT: movd %xmm2, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx +; X86-SSE-NEXT: divl 8(%ecx) ; X86-SSE-NEXT: movd %edx, %xmm2 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm4[2,3,2,3] -; X86-SSE-NEXT: movd %xmm4, %eax -; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; X86-SSE-NEXT: movd %xmm0, %ecx -; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm0 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] -; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0] +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1] +; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0] ; X86-SSE-NEXT: movl (%esp), %eax # 4-byte Reload ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl 32(%edi) +; X86-SSE-NEXT: divl 32(%ecx) ; X86-SSE-NEXT: movdqa {{.*#+}} xmm2 = [8199,8199,8199,8199] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm1[1,1,3,3] -; X86-SSE-NEXT: pmuludq %xmm2, %xmm1 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3] -; X86-SSE-NEXT: pmuludq %xmm2, %xmm4 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm4[0,2,2,3] -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm3[1,1,3,3] +; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,1,3,3] +; X86-SSE-NEXT: pmuludq %xmm2, %xmm0 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3] ; X86-SSE-NEXT: pmuludq %xmm2, %xmm3 ; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm3[0,2,2,3] +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] +; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm1[1,1,3,3] ; X86-SSE-NEXT: pmuludq %xmm2, %xmm1 ; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] +; X86-SSE-NEXT: pmuludq %xmm2, %xmm3 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm3[0,2,2,3] +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] ; X86-SSE-NEXT: imull $8199, %edx, %eax # imm = 0x2007 ; X86-SSE-NEXT: movl %eax, (%eax) -; X86-SSE-NEXT: movdqa %xmm3, (%eax) +; X86-SSE-NEXT: movdqa %xmm1, (%eax) ; X86-SSE-NEXT: movdqa %xmm0, (%eax) ; X86-SSE-NEXT: addl $4, %esp ; X86-SSE-NEXT: popl %esi @@ -2204,91 +2188,76 @@ define void @PR34947(ptr %p0, ptr %p1) nounwind { ; X64-SSE-LABEL: PR34947: ; X64-SSE: # %bb.0: ; X64-SSE-NEXT: movzwl 16(%rdi), %ecx -; X64-SSE-NEXT: movdqa (%rdi), %xmm3 -; X64-SSE-NEXT: movdqa (%rsi), %xmm0 -; X64-SSE-NEXT: movdqa 16(%rsi), %xmm1 -; X64-SSE-NEXT: pxor %xmm5, %xmm5 -; X64-SSE-NEXT: movdqa %xmm3, %xmm2 -; X64-SSE-NEXT: pextrw $7, %xmm3, %eax -; X64-SSE-NEXT: pextrw $4, %xmm3, %r8d -; X64-SSE-NEXT: pextrw $0, %xmm3, %r10d -; X64-SSE-NEXT: pextrw $1, %xmm3, %edi -; X64-SSE-NEXT: pextrw $3, %xmm3, %r9d -; X64-SSE-NEXT: movdqa %xmm3, %xmm4 -; X64-SSE-NEXT: punpcklwd {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3] -; X64-SSE-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm5[4],xmm2[5],xmm5[5],xmm2[6],xmm5[6],xmm2[7],xmm5[7] -; X64-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm1[3,3,3,3] -; X64-SSE-NEXT: movd %xmm3, %r11d -; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r11d -; X64-SSE-NEXT: movd %edx, %xmm3 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm2[2,3,2,3] -; X64-SSE-NEXT: movd %xmm5, %eax -; X64-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] -; X64-SSE-NEXT: movd %xmm5, %r11d +; X64-SSE-NEXT: movdqa (%rdi), %xmm2 +; X64-SSE-NEXT: pxor %xmm1, %xmm1 +; X64-SSE-NEXT: movdqa %xmm2, %xmm0 +; X64-SSE-NEXT: pextrw $7, %xmm2, %eax +; X64-SSE-NEXT: pextrw $4, %xmm2, %edi +; X64-SSE-NEXT: pextrw $1, %xmm2, %r8d +; X64-SSE-NEXT: pextrw $0, %xmm2, %r9d +; X64-SSE-NEXT: pextrw $3, %xmm2, %r10d +; X64-SSE-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3] +; X64-SSE-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r11d -; X64-SSE-NEXT: movd %edx, %xmm5 -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm3[0],xmm5[1],xmm3[1] -; X64-SSE-NEXT: movl %r8d, %eax +; X64-SSE-NEXT: divl 28(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm1 +; X64-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm0[2,3,2,3] +; X64-SSE-NEXT: movd %xmm3, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl 16(%rsi) +; X64-SSE-NEXT: divl 24(%rsi) ; X64-SSE-NEXT: movd %edx, %xmm3 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,1,1] -; X64-SSE-NEXT: movd %xmm2, %eax -; X64-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,1,1] -; X64-SSE-NEXT: movd %xmm1, %r8d -; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r8d -; X64-SSE-NEXT: movd %edx, %xmm1 ; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] -; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm5[0] -; X64-SSE-NEXT: movl %r10d, %eax +; X64-SSE-NEXT: movl %edi, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl (%rsi) +; X64-SSE-NEXT: divl 16(%rsi) ; X64-SSE-NEXT: movd %edx, %xmm1 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,1,1] -; X64-SSE-NEXT: movd %xmm2, %r8d -; X64-SSE-NEXT: movl %edi, %eax +; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X64-SSE-NEXT: movd %xmm0, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r8d -; X64-SSE-NEXT: movd %edx, %xmm2 -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[3,3,3,3] -; X64-SSE-NEXT: movd %xmm2, %edi +; X64-SSE-NEXT: divl 20(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm0 +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; X64-SSE-NEXT: movl %r8d, %eax +; X64-SSE-NEXT: xorl %edx, %edx +; X64-SSE-NEXT: divl 4(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm0 ; X64-SSE-NEXT: movl %r9d, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %edi -; X64-SSE-NEXT: movd %edx, %xmm2 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm4[2,3,2,3] -; X64-SSE-NEXT: movd %xmm4, %eax -; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; X64-SSE-NEXT: movd %xmm0, %edi +; X64-SSE-NEXT: divl (%rsi) +; X64-SSE-NEXT: movd %edx, %xmm3 +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1] +; X64-SSE-NEXT: movl %r10d, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %edi +; X64-SSE-NEXT: divl 12(%rsi) ; X64-SSE-NEXT: movd %edx, %xmm0 -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] -; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0] +; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; X64-SSE-NEXT: movd %xmm2, %eax +; X64-SSE-NEXT: xorl %edx, %edx +; X64-SSE-NEXT: divl 8(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm2 +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1] +; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm2[0] ; X64-SSE-NEXT: movl %ecx, %eax ; X64-SSE-NEXT: xorl %edx, %edx ; X64-SSE-NEXT: divl 32(%rsi) ; X64-SSE-NEXT: movdqa {{.*#+}} xmm0 = [8199,8199,8199,8199] -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] -; X64-SSE-NEXT: pmuludq %xmm0, %xmm1 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] -; X64-SSE-NEXT: pmuludq %xmm0, %xmm2 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,2,2,3] -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] ; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm3[1,1,3,3] ; X64-SSE-NEXT: pmuludq %xmm0, %xmm3 ; X64-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm3[0,2,2,3] ; X64-SSE-NEXT: pmuludq %xmm0, %xmm2 +; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,2,2,3] +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm2[0],xmm3[1],xmm2[1] +; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] +; X64-SSE-NEXT: pmuludq %xmm0, %xmm1 +; X64-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] +; X64-SSE-NEXT: pmuludq %xmm0, %xmm2 ; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm2[0,2,2,3] -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1] +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] ; X64-SSE-NEXT: imull $8199, %edx, %eax # imm = 0x2007 ; X64-SSE-NEXT: movl %eax, (%rax) -; X64-SSE-NEXT: movdqa %xmm3, (%rax) ; X64-SSE-NEXT: movdqa %xmm1, (%rax) +; X64-SSE-NEXT: movdqa %xmm3, (%rax) ; X64-SSE-NEXT: retq ; ; X64-AVX1-LABEL: PR34947: -- GitLab From 91896607ffb84561a7a2e466a00fdf1938c5bb63 Mon Sep 17 00:00:00 2001 From: Brandon Wu Date: Wed, 27 Mar 2024 23:03:13 +0800 Subject: [PATCH 067/541] [RISCV] RISCV vector calling convention (1/2) (#77560) [RISCV] RISCV vector calling convention (1/2) This is the vector calling convention based on https://github.com/riscv-non-isa/riscv-elf-psabi-doc, the idea is to split between "scalar" callee-saved registers and "vector" callee-saved registers. "scalar" ones remain the original strategy, however, "vector" ones are handled together with RVV objects. The stack layout would be: |--------------------------| <-- FP | callee-allocated save | | area for register varargs| |--------------------------| | callee-saved registers | <-- scalar callee-saved | (scalar) | |--------------------------| | RVV alignment padding | |--------------------------| | callee-saved registers | <-- vector callee-saved | (vector) | |--------------------------| | RVV objects | |--------------------------| | padding before RVV | |--------------------------| | scalar local variables | |--------------------------| <-- BP | variable size objects | |--------------------------| <-- SP Note: This patch doesn't contain "tuple" type, e.g. vint32m1x2. It will be handled in https://github.com/riscv-non-isa/riscv-elf-psabi-doc (2/2). Differential Revision: https://reviews.llvm.org/D154576 --- clang/include/clang-c/Index.h | 1 + clang/include/clang/Basic/Attr.td | 7 ++ clang/include/clang/Basic/AttrDocs.td | 11 +++ clang/include/clang/Basic/Specifiers.h | 43 ++++---- clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/Type.cpp | 4 + clang/lib/AST/TypePrinter.cpp | 6 ++ clang/lib/Basic/Targets/RISCV.cpp | 11 +++ clang/lib/Basic/Targets/RISCV.h | 2 + clang/lib/CodeGen/CGCall.cpp | 6 ++ clang/lib/CodeGen/CGDebugInfo.cpp | 2 + clang/lib/Sema/SemaDeclAttr.cpp | 7 ++ clang/lib/Sema/SemaType.cpp | 5 +- .../RISCV/riscv-vector-callingconv-llvm-ir.c | 34 +++++++ .../riscv-vector-callingconv-llvm-ir.cpp | 32 ++++++ .../CodeGen/RISCV/riscv-vector-callingconv.c | 17 ++++ .../RISCV/riscv-vector-callingconv.cpp | 35 +++++++ clang/tools/libclang/CXType.cpp | 1 + llvm/include/llvm/AsmParser/LLToken.h | 1 + llvm/include/llvm/BinaryFormat/Dwarf.def | 1 + llvm/include/llvm/IR/CallingConv.h | 3 + llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 4 + llvm/lib/IR/AsmWriter.cpp | 3 + llvm/lib/Target/RISCV/RISCVCallingConv.td | 13 +++ llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 97 +++++++++++++------ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 1 + llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 15 +++ .../CodeGen/RISCV/rvv/callee-saved-regs.ll | 95 ++++++++++++++++++ 29 files changed, 409 insertions(+), 50 deletions(-) create mode 100644 clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c create mode 100644 clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp create mode 100644 clang/test/CodeGen/RISCV/riscv-vector-callingconv.c create mode 100644 clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp create mode 100644 llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 60db3cf0966c..7a8bd985a91f 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2991,6 +2991,7 @@ enum CXCallingConv { CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, CXCallingConv_PreserveNone = 20, + CXCallingConv_RISCVVectorCall = 21, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 318d4e5ac5ba..80e607525a0a 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3011,6 +3011,13 @@ def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr { let Documentation = [PreserveNoneDocs]; } +def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr { + let Spellings = [CXX11<"riscv", "vector_cc">, + C23<"riscv", "vector_cc">, + Clang<"riscv_vector_cc">]; + let Documentation = [RISCVVectorCCDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 384aebbdf2e3..3ea4d676b4f8 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5494,6 +5494,17 @@ for clang builtin functions. }]; } +def RISCVVectorCCDocs : Documentation { + let Category = DocCatCallingConvs; + let Heading = "riscv::vector_cc, riscv_vector_cc, clang::riscv_vector_cc"; + let Content = [{ +The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15 +registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need +to save these registers before function calls, and callees only need to save +them if they use them. + }]; +} + def PreferredNameDocs : Documentation { let Category = DocCatDecl; let Content = [{ diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 8586405825cf..fb11e8212f8b 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -273,29 +273,30 @@ namespace clang { /// CallingConv - Specifies the calling convention that a function uses. enum CallingConv { - CC_C, // __attribute__((cdecl)) - CC_X86StdCall, // __attribute__((stdcall)) - CC_X86FastCall, // __attribute__((fastcall)) - CC_X86ThisCall, // __attribute__((thiscall)) - CC_X86VectorCall, // __attribute__((vectorcall)) - CC_X86Pascal, // __attribute__((pascal)) - CC_Win64, // __attribute__((ms_abi)) - CC_X86_64SysV, // __attribute__((sysv_abi)) - CC_X86RegCall, // __attribute__((regcall)) - CC_AAPCS, // __attribute__((pcs("aapcs"))) - CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) - CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) - CC_SpirFunction, // default for OpenCL functions on SPIR target - CC_OpenCLKernel, // inferred for OpenCL kernels - CC_Swift, // __attribute__((swiftcall)) + CC_C, // __attribute__((cdecl)) + CC_X86StdCall, // __attribute__((stdcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall, // __attribute__((thiscall)) + CC_X86VectorCall, // __attribute__((vectorcall)) + CC_X86Pascal, // __attribute__((pascal)) + CC_Win64, // __attribute__((ms_abi)) + CC_X86_64SysV, // __attribute__((sysv_abi)) + CC_X86RegCall, // __attribute__((regcall)) + CC_AAPCS, // __attribute__((pcs("aapcs"))) + CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) + CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) + CC_SpirFunction, // default for OpenCL functions on SPIR target + CC_OpenCLKernel, // inferred for OpenCL kernels + CC_Swift, // __attribute__((swiftcall)) CC_SwiftAsync, // __attribute__((swiftasynccall)) - CC_PreserveMost, // __attribute__((preserve_most)) - CC_PreserveAll, // __attribute__((preserve_all)) + CC_PreserveMost, // __attribute__((preserve_most)) + CC_PreserveAll, // __attribute__((preserve_all)) CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) - CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) - CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) - CC_M68kRTD, // __attribute__((m68k_rtd)) - CC_PreserveNone, // __attribute__((preserve_none)) + CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) + CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) + CC_M68kRTD, // __attribute__((m68k_rtd)) + CC_PreserveNone, // __attribute__((preserve_none)) + CC_RISCVVectorCall, // __attribute__((riscv_vector_cc)) }; /// Checks whether the given calling convention supports variadic diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index f619d657ae9f..425f84e8af1f 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3445,6 +3445,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_PreserveAll: case CC_M68kRTD: case CC_PreserveNone: + case CC_RISCVVectorCall: // FIXME: we should be mangling all of the above. return ""; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index d2ffb23845ac..8f3e26d46019 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3484,6 +3484,9 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_PreserveAll: return "preserve_all"; case CC_M68kRTD: return "m68k_rtd"; case CC_PreserveNone: return "preserve_none"; + // clang-format off + case CC_RISCVVectorCall: return "riscv_vector_cc"; + // clang-format on } llvm_unreachable("Invalid calling convention."); @@ -4074,6 +4077,7 @@ bool AttributedType::isCallingConv() const { case attr::PreserveAll: case attr::M68kRTD: case attr::PreserveNone: + case attr::RISCVVectorCC: return true; } llvm_unreachable("invalid attr kind"); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index f176d043d525..0aa1d9327d77 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1071,6 +1071,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_PreserveNone: OS << " __attribute__((preserve_none))"; break; + case CC_RISCVVectorCall: + OS << "__attribute__((riscv_vector_cc))"; + break; } } @@ -1960,6 +1963,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::PreserveNone: OS << "preserve_none"; break; + case attr::RISCVVectorCC: + OS << "riscv_vector_cc"; + break; case attr::NoDeref: OS << "noderef"; break; diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index a6d4af2b8811..f3d705e1551f 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -467,3 +467,14 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { } return Ret; } + +TargetInfo::CallingConvCheckResult +RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_RISCVVectorCall: + return CCCR_OK; + } +} diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index bfbdafb682c8..78580b5b1c10 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -110,6 +110,8 @@ public: bool hasBFloat16Type() const override { return true; } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; + bool useFP16ConversionIntrinsics() const override { return false; } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 475d96b0e87d..b8adf5c26b3a 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -74,6 +74,9 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_SwiftAsync: return llvm::CallingConv::SwiftTail; case CC_M68kRTD: return llvm::CallingConv::M68k_RTD; case CC_PreserveNone: return llvm::CallingConv::PreserveNone; + // clang-format off + case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall; + // clang-format on } } @@ -260,6 +263,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D, if (D->hasAttr()) return CC_PreserveNone; + if (D->hasAttr()) + return CC_RISCVVectorCall; + return CC_C; } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0e20de2005b2..2a385d85aa2b 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1452,6 +1452,8 @@ static unsigned getDwarfCC(CallingConv CC) { return llvm::dwarf::DW_CC_LLVM_M68kRTD; case CC_PreserveNone: return llvm::dwarf::DW_CC_LLVM_PreserveNone; + case CC_RISCVVectorCall: + return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall; } return 0; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0a62c656d824..f25f3afd0f4a 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5271,6 +5271,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case ParsedAttr::AT_PreserveNone: D->addAttr(::new (S.Context) PreserveNoneAttr(S.Context, AL)); return; + case ParsedAttr::AT_RISCVVectorCC: + D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL)); + return; default: llvm_unreachable("unexpected attribute kind"); } @@ -5475,6 +5478,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_PreserveNone: CC = CC_PreserveNone; break; + case ParsedAttr::AT_RISCVVectorCC: + CC = CC_RISCVVectorCall; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -9637,6 +9643,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_AMDGPUKernelCall: case ParsedAttr::AT_M68kRTD: case ParsedAttr::AT_PreserveNone: + case ParsedAttr::AT_RISCVVectorCC: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d7521a5363a3..fd94caa4e1d4 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -138,7 +138,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_PreserveMost: \ case ParsedAttr::AT_PreserveAll: \ case ParsedAttr::AT_M68kRTD: \ - case ParsedAttr::AT_PreserveNone + case ParsedAttr::AT_PreserveNone: \ + case ParsedAttr::AT_RISCVVectorCC // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ @@ -7939,6 +7940,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_PreserveNone: return createSimpleAttr(Ctx, Attr); + case ParsedAttr::AT_RISCVVectorCC: + return createSimpleAttr(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c new file mode 100644 index 000000000000..072d8a863d45 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c @@ -0,0 +1,34 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s +// RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s + +#include + +// CHECK-LLVM: call riscv_vector_cc @bar +vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call riscv_vector_cc @bar +[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call @baz +vint32m1_t baz(vint32m1_t input); +vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = baz(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp new file mode 100644 index 000000000000..c01aeb21f675 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp @@ -0,0 +1,32 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s + +#include + +// CHECK-LLVM: call riscv_vector_cc @_Z3baru15__rvv_int32m1_t +vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call riscv_vector_cc @_Z3baru15__rvv_int32m1_t +[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call @_Z3bazu15__rvv_int32m1_t +vint32m1_t baz(vint32m1_t input); +vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = baz(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c new file mode 100644 index 000000000000..5c35901799b4 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -std=c23 -triple riscv64 -target-feature +v -verify + +__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}} + +__attribute__((riscv_vector_cc)) void func(); +__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}} + +void test_no_attribute(int); // expected-note {{previous declaration is here}} +void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}} + +[[riscv::vector_cc]] void func2(); +[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}} + +void test_no_attribute2(int); // expected-note {{previous declaration is here}} +[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp new file mode 100644 index 000000000000..264bb7d9ad7c --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -triple riscv64 -target-feature +v -verify + +__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}} + +__attribute__((riscv_vector_cc)) void func(); +__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}} + +void test_no_attribute(int); // expected-note {{previous declaration is here}} +void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +class test_cc { + __attribute__((riscv_vector_cc)) void member_func(); +}; + +void test_lambda() { + __attribute__((riscv_vector_cc)) auto lambda = []() { // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'auto'}} + }; +} + +[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}} + +[[riscv::vector_cc]] void func2(); +[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}} + +void test_no_attribute2(int); // expected-note {{previous declaration is here}} +[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +class test_cc2 { + [[riscv::vector_cc]] void member_func(); +}; + +void test_lambda2() { + [[riscv::vector_cc]] auto lambda = []() { // expected-warning {{'vector_cc' only applies to function types; type here is 'auto'}} + }; +} diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 292d524f00ab..991767dc4c49 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -680,6 +680,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(PreserveAll); TCALLINGCONV(M68kRTD); TCALLINGCONV(PreserveNone); + TCALLINGCONV(RISCVVectorCall); case CC_SpirFunction: return CXCallingConv_Unexposed; case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed; case CC_OpenCLKernel: return CXCallingConv_Unexposed; diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 5863a8d6e8ee..65ccb1b81b3a 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -181,6 +181,7 @@ enum Kind { kw_tailcc, kw_m68k_rtdcc, kw_graalcc, + kw_riscv_vector_cc, // Attributes: kw_attributes, diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index e70b58d5ea50..d8927c6202fd 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -1040,6 +1040,7 @@ HANDLE_DW_CC(0xca, LLVM_PreserveAll) HANDLE_DW_CC(0xcb, LLVM_X86RegCall) HANDLE_DW_CC(0xcc, LLVM_M68kRTD) HANDLE_DW_CC(0xcd, LLVM_PreserveNone) +HANDLE_DW_CC(0xce, LLVM_RISCVVectorCall) // From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently // generated by any toolchain. It is used internally to GDB to indicate OpenCL // C functions that have been compiled with the IBM XL C for OpenCL compiler and diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h index ef8aaf52f4e6..a05d1a4d5878 100644 --- a/llvm/include/llvm/IR/CallingConv.h +++ b/llvm/include/llvm/IR/CallingConv.h @@ -264,6 +264,9 @@ namespace CallingConv { /// except that the first parameter is mapped to x9. ARM64EC_Thunk_Native = 109, + /// Calling convention used for RISC-V V-extension. + RISCV_VectorCall = 110, + /// The highest possible ID. Must be some 2^k - 1. MaxID = 1023 }; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 02f64fcfac4f..2301a27731ea 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -640,6 +640,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(tailcc); KEYWORD(m68k_rtdcc); KEYWORD(graalcc); + KEYWORD(riscv_vector_cc); KEYWORD(cc); KEYWORD(c); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index f0be021668af..41d48e522620 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -2143,6 +2143,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) { /// ::= 'tailcc' /// ::= 'm68k_rtdcc' /// ::= 'graalcc' +/// ::= 'riscv_vector_cc' /// ::= 'cc' UINT /// bool LLParser::parseOptionalCallingConv(unsigned &CC) { @@ -2213,6 +2214,9 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) { case lltok::kw_tailcc: CC = CallingConv::Tail; break; case lltok::kw_m68k_rtdcc: CC = CallingConv::M68k_RTD; break; case lltok::kw_graalcc: CC = CallingConv::GRAAL; break; + case lltok::kw_riscv_vector_cc: + CC = CallingConv::RISCV_VectorCall; + break; case lltok::kw_cc: { Lex.Lex(); return parseUInt32(CC); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 38c191a2dec6..84690f026139 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -363,6 +363,9 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break; case CallingConv::AMDGPU_Gfx: Out << "amdgpu_gfx"; break; case CallingConv::M68k_RTD: Out << "m68k_rtdcc"; break; + case CallingConv::RISCV_VectorCall: + Out << "riscv_vector_cc"; + break; } } diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.td b/llvm/lib/Target/RISCV/RISCVCallingConv.td index 11b716f20f37..ad06f4774377 100644 --- a/llvm/lib/Target/RISCV/RISCVCallingConv.td +++ b/llvm/lib/Target/RISCV/RISCVCallingConv.td @@ -26,6 +26,19 @@ def CSR_ILP32D_LP64D : CalleeSavedRegs<(add CSR_ILP32_LP64, F8_D, F9_D, (sequence "F%u_D", 18, 27))>; +defvar CSR_V = (add (sequence "V%u", 1, 7), (sequence "V%u", 24, 31), + V2M2, V4M2, V6M2, V24M2, V26M2, V28M2, V30M2, + V4M4, V24M4, V28M4, V24M8); + +def CSR_ILP32_LP64_V + : CalleeSavedRegs<(add CSR_ILP32_LP64, CSR_V)>; + +def CSR_ILP32F_LP64F_V + : CalleeSavedRegs<(add CSR_ILP32F_LP64F, CSR_V)>; + +def CSR_ILP32D_LP64D_V + : CalleeSavedRegs<(add CSR_ILP32D_LP64D, CSR_V)>; + // Needed for implementation of RISCVRegisterInfo::getNoPreservedMask() def CSR_NoRegs : CalleeSavedRegs<(add)>; diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 39f2b3f62a9a..39075c81b292 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -388,6 +388,21 @@ getUnmanagedCSI(const MachineFunction &MF, return NonLibcallCSI; } +static SmallVector +getRVVCalleeSavedInfo(const MachineFunction &MF, + const std::vector &CSI) { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + SmallVector RVVCSI; + + for (auto &CS : CSI) { + int FI = CS.getFrameIdx(); + if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) + RVVCSI.push_back(CS); + } + + return RVVCSI; +} + void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, @@ -590,6 +605,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, // directives. for (const auto &Entry : CSI) { int FrameIdx = Entry.getFrameIdx(); + if (FrameIdx >= 0 && + MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector) + continue; + int64_t Offset = MFI.getObjectOffset(FrameIdx); Register Reg = Entry.getReg(); unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( @@ -726,7 +745,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, const auto &CSI = getUnmanagedCSI(MF, MFI.getCalleeSavedInfo()); - // Skip to before the restores of callee-saved registers + // Skip to before the restores of scalar callee-saved registers // FIXME: assumes exactly one instruction is used to restore each // callee-saved register. auto LastFrameDestroy = MBBI; @@ -1029,15 +1048,24 @@ RISCVFrameLowering::assignRVVStackObjectOffsets(MachineFunction &MF) const { MachineFrameInfo &MFI = MF.getFrameInfo(); // Create a buffer of RVV objects to allocate. SmallVector ObjectsToAllocate; - for (int I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I) { - unsigned StackID = MFI.getStackID(I); - if (StackID != TargetStackID::ScalableVector) - continue; - if (MFI.isDeadObjectIndex(I)) - continue; + auto pushRVVObjects = [&](int FIBegin, int FIEnd) { + for (int I = FIBegin, E = FIEnd; I != E; ++I) { + unsigned StackID = MFI.getStackID(I); + if (StackID != TargetStackID::ScalableVector) + continue; + if (MFI.isDeadObjectIndex(I)) + continue; - ObjectsToAllocate.push_back(I); - } + ObjectsToAllocate.push_back(I); + } + }; + // First push RVV Callee Saved object, then push RVV stack object + std::vector &CSI = MF.getFrameInfo().getCalleeSavedInfo(); + const auto &RVVCSI = getRVVCalleeSavedInfo(MF, CSI); + if (!RVVCSI.empty()) + pushRVVObjects(RVVCSI[0].getFrameIdx(), + RVVCSI[RVVCSI.size() - 1].getFrameIdx() + 1); + pushRVVObjects(0, MFI.getObjectIndexEnd() - RVVCSI.size()); // The minimum alignment is 16 bytes. Align RVVStackAlign(16); @@ -1487,13 +1515,19 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters( // Manually spill values not spilled by libcall & Push/Pop. const auto &UnmanagedCSI = getUnmanagedCSI(*MF, CSI); - for (auto &CS : UnmanagedCSI) { - // Insert the spill to the stack frame. - Register Reg = CS.getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(MBB, MI, Reg, !MBB.isLiveIn(Reg), CS.getFrameIdx(), - RC, TRI, Register()); - } + const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, CSI); + + auto storeRegToStackSlot = [&](decltype(UnmanagedCSI) CSInfo) { + for (auto &CS : CSInfo) { + // Insert the spill to the stack frame. + Register Reg = CS.getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(MBB, MI, Reg, !MBB.isLiveIn(Reg), + CS.getFrameIdx(), RC, TRI, Register()); + } + }; + storeRegToStackSlot(UnmanagedCSI); + storeRegToStackSlot(RVVCSI); return true; } @@ -1511,19 +1545,26 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters( DL = MI->getDebugLoc(); // Manually restore values not restored by libcall & Push/Pop. - // Keep the same order as in the prologue. There is no need to reverse the - // order in the epilogue. In addition, the return address will be restored - // first in the epilogue. It increases the opportunity to avoid the - // load-to-use data hazard between loading RA and return by RA. - // loadRegFromStackSlot can insert multiple instructions. + // Reverse the restore order in epilog. In addition, the return + // address will be restored first in the epilogue. It increases + // the opportunity to avoid the load-to-use data hazard between + // loading RA and return by RA. loadRegFromStackSlot can insert + // multiple instructions. const auto &UnmanagedCSI = getUnmanagedCSI(*MF, CSI); - for (auto &CS : UnmanagedCSI) { - Register Reg = CS.getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, TRI, - Register()); - assert(MI != MBB.begin() && "loadRegFromStackSlot didn't insert any code!"); - } + const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, CSI); + + auto loadRegFromStackSlot = [&](decltype(UnmanagedCSI) CSInfo) { + for (auto &CS : CSInfo) { + Register Reg = CS.getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, TRI, + Register()); + assert(MI != MBB.begin() && + "loadRegFromStackSlot didn't insert any code!"); + } + }; + loadRegFromStackSlot(RVVCSI); + loadRegFromStackSlot(UnmanagedCSI); RISCVMachineFunctionInfo *RVFI = MF->getInfo(); if (RVFI->isPushable(*MF)) { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index ca78648c6aa9..564fda674317 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -18724,6 +18724,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments( case CallingConv::Fast: case CallingConv::SPIR_KERNEL: case CallingConv::GRAAL: + case CallingConv::RISCV_VectorCall: break; case CallingConv::GHC: if (Subtarget.isRVE()) diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 74d65324b95d..11c3f2d57eb0 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -71,6 +71,9 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { : CSR_Interrupt_SaveList; } + bool HasVectorCSR = + MF->getFunction().getCallingConv() == CallingConv::RISCV_VectorCall; + switch (Subtarget.getTargetABI()) { default: llvm_unreachable("Unrecognized ABI"); @@ -79,12 +82,18 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { return CSR_ILP32E_LP64E_SaveList; case RISCVABI::ABI_ILP32: case RISCVABI::ABI_LP64: + if (HasVectorCSR) + return CSR_ILP32_LP64_V_SaveList; return CSR_ILP32_LP64_SaveList; case RISCVABI::ABI_ILP32F: case RISCVABI::ABI_LP64F: + if (HasVectorCSR) + return CSR_ILP32F_LP64F_V_SaveList; return CSR_ILP32F_LP64F_SaveList; case RISCVABI::ABI_ILP32D: case RISCVABI::ABI_LP64D: + if (HasVectorCSR) + return CSR_ILP32D_LP64D_V_SaveList; return CSR_ILP32D_LP64D_SaveList; } } @@ -665,12 +674,18 @@ RISCVRegisterInfo::getCallPreservedMask(const MachineFunction & MF, return CSR_ILP32E_LP64E_RegMask; case RISCVABI::ABI_ILP32: case RISCVABI::ABI_LP64: + if (CC == CallingConv::RISCV_VectorCall) + return CSR_ILP32_LP64_V_RegMask; return CSR_ILP32_LP64_RegMask; case RISCVABI::ABI_ILP32F: case RISCVABI::ABI_LP64F: + if (CC == CallingConv::RISCV_VectorCall) + return CSR_ILP32F_LP64F_V_RegMask; return CSR_ILP32F_LP64F_RegMask; case RISCVABI::ABI_ILP32D: case RISCVABI::ABI_LP64D: + if (CC == CallingConv::RISCV_VectorCall) + return CSR_ILP32D_LP64D_V_RegMask; return CSR_ILP32D_LP64D_RegMask; } } diff --git a/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll b/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll new file mode 100644 index 000000000000..84936d88e187 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+m -mattr=+v -O2 < %s \ +; RUN: | FileCheck --check-prefix=SPILL-O2 %s + +define @test_vector_std( %va) nounwind { +; SPILL-O2-LABEL: test_vector_std: +; SPILL-O2: # %bb.0: # %entry +; SPILL-O2-NEXT: addi sp, sp, -16 +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 1 +; SPILL-O2-NEXT: sub sp, sp, a0 +; SPILL-O2-NEXT: addi a0, sp, 16 +; SPILL-O2-NEXT: vs1r.v v8, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: #APP +; SPILL-O2-NEXT: #NO_APP +; SPILL-O2-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 1 +; SPILL-O2-NEXT: add sp, sp, a0 +; SPILL-O2-NEXT: addi sp, sp, 16 +; SPILL-O2-NEXT: ret +entry: + call void asm sideeffect "", + "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() + + ret %va +} + +define riscv_vector_cc @test_vector_callee( %va) nounwind { +; SPILL-O2-LABEL: test_vector_callee: +; SPILL-O2: # %bb.0: # %entry +; SPILL-O2-NEXT: addi sp, sp, -16 +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 4 +; SPILL-O2-NEXT: sub sp, sp, a0 +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 4 +; SPILL-O2-NEXT: sub a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs1r.v v1, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: li a1, 13 +; SPILL-O2-NEXT: mul a0, a0, a1 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs2r.v v2, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 3 +; SPILL-O2-NEXT: add a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs4r.v v4, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs8r.v v24, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: addi a0, sp, 16 +; SPILL-O2-NEXT: vs1r.v v8, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: #APP +; SPILL-O2-NEXT: #NO_APP +; SPILL-O2-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 4 +; SPILL-O2-NEXT: sub a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl1r.v v1, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: li a1, 13 +; SPILL-O2-NEXT: mul a0, a0, a1 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl2r.v v2, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 3 +; SPILL-O2-NEXT: add a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl4r.v v4, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl8r.v v24, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 4 +; SPILL-O2-NEXT: add sp, sp, a0 +; SPILL-O2-NEXT: addi sp, sp, 16 +; SPILL-O2-NEXT: ret +entry: + call void asm sideeffect "", + "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() + + ret %va +} -- GitLab From 58de1e2c5eee548a9b365e3b1554d87317072ad9 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 27 Mar 2024 15:05:58 +0000 Subject: [PATCH 068/541] Fix stack layout for frames larger than 2gb (#84114) For very large stack frames, the offset from the stack pointer to a local can be more than 2^31 which overflows various `int` offsets in the frame lowering code. This patch updates the frame lowering code to calculate the offsets as 64-bit values and resolves the overflows, resulting in the correct codegen for very large frames. Fixes #48911 --- llvm/include/llvm/CodeGen/MachineFrameInfo.h | 14 +++---- .../llvm/CodeGen/TargetFrameLowering.h | 4 +- llvm/include/llvm/MC/MCAsmBackend.h | 2 +- llvm/include/llvm/MC/MCDwarf.h | 40 +++++++++---------- llvm/lib/CodeGen/CFIInstrInserter.cpp | 10 ++--- llvm/lib/CodeGen/MachineFrameInfo.cpp | 2 +- llvm/lib/CodeGen/PrologEpilogInserter.cpp | 4 +- llvm/lib/MC/MCDwarf.cpp | 6 +-- .../MCTargetDesc/AArch64AsmBackend.cpp | 10 ++--- llvm/lib/Target/ARM/ARMFrameLowering.cpp | 4 +- .../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 2 +- .../ARM/MCTargetDesc/ARMAsmBackendDarwin.h | 2 +- .../Target/Hexagon/HexagonFrameLowering.cpp | 4 +- .../lib/Target/MSP430/MSP430FrameLowering.cpp | 2 +- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 13 +++--- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 14 ++++--- llvm/lib/Target/X86/X86FrameLowering.cpp | 28 ++++++------- llvm/lib/Target/X86/X86FrameLowering.h | 5 ++- llvm/lib/Target/X86/X86RegisterInfo.cpp | 10 +++-- llvm/test/CodeGen/PowerPC/huge-frame-size.ll | 2 +- llvm/test/CodeGen/X86/huge-stack.ll | 24 +++++++++++ 21 files changed, 116 insertions(+), 86 deletions(-) create mode 100644 llvm/test/CodeGen/X86/huge-stack.ll diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 0fe73fec7ee6..ad6142b46515 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -251,7 +251,7 @@ private: /// targets, this value is only used when generating debug info (via /// TargetRegisterInfo::getFrameIndexReference); when generating code, the /// corresponding adjustments are performed directly. - int OffsetAdjustment = 0; + int64_t OffsetAdjustment = 0; /// The prolog/epilog code inserter may process objects that require greater /// alignment than the default alignment the target provides. @@ -280,7 +280,7 @@ private: /// setup/destroy pseudo instructions (as defined in the TargetFrameInfo /// class). This information is important for frame pointer elimination. /// It is only valid during and after prolog/epilog code insertion. - unsigned MaxCallFrameSize = ~0u; + uint64_t MaxCallFrameSize = ~UINT64_C(0); /// The number of bytes of callee saved registers that the target wants to /// report for the current function in the CodeView S_FRAMEPROC record. @@ -591,10 +591,10 @@ public: uint64_t estimateStackSize(const MachineFunction &MF) const; /// Return the correction for frame offsets. - int getOffsetAdjustment() const { return OffsetAdjustment; } + int64_t getOffsetAdjustment() const { return OffsetAdjustment; } /// Set the correction for frame offsets. - void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } + void setOffsetAdjustment(int64_t Adj) { OffsetAdjustment = Adj; } /// Return the alignment in bytes that this function must be aligned to, /// which is greater than the default stack alignment provided by the target. @@ -655,7 +655,7 @@ public: /// CallFrameSetup/Destroy pseudo instructions are used by the target, and /// then only during or after prolog/epilog code insertion. /// - unsigned getMaxCallFrameSize() const { + uint64_t getMaxCallFrameSize() const { // TODO: Enable this assert when targets are fixed. //assert(isMaxCallFrameSizeComputed() && "MaxCallFrameSize not computed yet"); if (!isMaxCallFrameSizeComputed()) @@ -663,9 +663,9 @@ public: return MaxCallFrameSize; } bool isMaxCallFrameSizeComputed() const { - return MaxCallFrameSize != ~0u; + return MaxCallFrameSize != ~UINT64_C(0); } - void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } + void setMaxCallFrameSize(uint64_t S) { MaxCallFrameSize = S; } /// Returns how many bytes of callee-saved registers the target pushed in the /// prologue. Only used for debug info. diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 0b9cacecc7cb..72978b2f746d 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -51,7 +51,7 @@ public: // Maps a callee saved register to a stack slot with a fixed offset. struct SpillSlot { unsigned Reg; - int Offset; // Offset relative to stack pointer on function entry. + int64_t Offset; // Offset relative to stack pointer on function entry. }; struct DwarfFrameBase { @@ -66,7 +66,7 @@ public: // Used with FrameBaseKind::Register. unsigned Reg; // Used with FrameBaseKind::CFA. - int Offset; + int64_t Offset; struct WasmFrameBase WasmLoc; } Location; }; diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index 01a64fb425a9..689e3cd5dbf2 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -232,7 +232,7 @@ public: virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} /// Generate the compact unwind encoding for the CFI instructions. - virtual uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + virtual uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const { return 0; } diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h index 18056c5fdf81..150b48eedc37 100644 --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -508,7 +508,7 @@ private: MCSymbol *Label; unsigned Register; union { - int Offset; + int64_t Offset; unsigned Register2; }; unsigned AddressSpace = ~0u; @@ -516,7 +516,7 @@ private: std::vector Values; std::string Comment; - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, SMLoc Loc, + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, SMLoc Loc, StringRef V = "", StringRef Comment = "") : Operation(Op), Label(L), Register(R), Offset(O), Loc(Loc), Values(V.begin(), V.end()), Comment(Comment) { @@ -528,7 +528,7 @@ private: assert(Op == OpRegister); } - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS, + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, unsigned AS, SMLoc Loc) : Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS), Loc(Loc) { @@ -538,8 +538,8 @@ private: public: /// .cfi_def_cfa defines a rule for computing CFA as: take address from /// Register and add Offset to it. - static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset, - SMLoc Loc = {}) { + static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, + int64_t Offset, SMLoc Loc = {}) { return MCCFIInstruction(OpDefCfa, L, Register, Offset, Loc); } @@ -547,13 +547,13 @@ public: /// on Register will be used instead of the old one. Offset remains the same. static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, Loc); + return MCCFIInstruction(OpDefCfaRegister, L, Register, INT64_C(0), Loc); } /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register /// remains the same, but offset is new. Note that it is the absolute offset /// that will be added to a defined register to the compute CFA address. - static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset, + static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc = {}) { return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, Loc); } @@ -561,7 +561,7 @@ public: /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but /// Offset is a relative value that is added/subtracted from the previous /// offset. - static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment, + static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int64_t Adjustment, SMLoc Loc = {}) { return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, Loc); } @@ -581,7 +581,7 @@ public: /// .cfi_offset Previous value of Register is saved at offset Offset /// from CFA. static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, - int Offset, SMLoc Loc = {}) { + int64_t Offset, SMLoc Loc = {}) { return MCCFIInstruction(OpOffset, L, Register, Offset, Loc); } @@ -589,7 +589,7 @@ public: /// Offset from the current CFA register. This is transformed to .cfi_offset /// using the known displacement of the CFA register from the CFA. static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, - int Offset, SMLoc Loc = {}) { + int64_t Offset, SMLoc Loc = {}) { return MCCFIInstruction(OpRelOffset, L, Register, Offset, Loc); } @@ -602,12 +602,12 @@ public: /// .cfi_window_save SPARC register window is saved. static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpWindowSave, L, 0, 0, Loc); + return MCCFIInstruction(OpWindowSave, L, 0, INT64_C(0), Loc); } /// .cfi_negate_ra_state AArch64 negate RA state. static MCCFIInstruction createNegateRAState(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpNegateRAState, L, 0, 0, Loc); + return MCCFIInstruction(OpNegateRAState, L, 0, INT64_C(0), Loc); } /// .cfi_restore says that the rule for Register is now the same as it @@ -615,31 +615,31 @@ public: /// by .cfi_startproc were executed. static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpRestore, L, Register, 0, Loc); + return MCCFIInstruction(OpRestore, L, Register, INT64_C(0), Loc); } /// .cfi_undefined From now on the previous value of Register can't be /// restored anymore. static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpUndefined, L, Register, 0, Loc); + return MCCFIInstruction(OpUndefined, L, Register, INT64_C(0), Loc); } /// .cfi_same_value Current value of Register is the same as in the /// previous frame. I.e., no restoration is needed. static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpSameValue, L, Register, 0, Loc); + return MCCFIInstruction(OpSameValue, L, Register, INT64_C(0), Loc); } /// .cfi_remember_state Save all current rules for all registers. static MCCFIInstruction createRememberState(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpRememberState, L, 0, 0, Loc); + return MCCFIInstruction(OpRememberState, L, 0, INT64_C(0), Loc); } /// .cfi_restore_state Restore the previously saved state. static MCCFIInstruction createRestoreState(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpRestoreState, L, 0, 0, Loc); + return MCCFIInstruction(OpRestoreState, L, 0, INT64_C(0), Loc); } /// .cfi_escape Allows the user to add arbitrary bytes to the unwind @@ -650,7 +650,7 @@ public: } /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE - static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size, + static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size, SMLoc Loc = {}) { return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, Loc); } @@ -677,7 +677,7 @@ public: return AddressSpace; } - int getOffset() const { + int64_t getOffset() const { assert(Operation == OpDefCfa || Operation == OpOffset || Operation == OpRelOffset || Operation == OpDefCfaOffset || Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize || @@ -705,7 +705,7 @@ struct MCDwarfFrameInfo { unsigned CurrentCfaRegister = 0; unsigned PersonalityEncoding = 0; unsigned LsdaEncoding = 0; - uint32_t CompactUnwindEncoding = 0; + uint64_t CompactUnwindEncoding = 0; bool IsSignalFrame = false; bool IsSimple = false; unsigned RAReg = static_cast(INT_MAX); diff --git a/llvm/lib/CodeGen/CFIInstrInserter.cpp b/llvm/lib/CodeGen/CFIInstrInserter.cpp index 87b062a16df1..776cc13ccd20 100644 --- a/llvm/lib/CodeGen/CFIInstrInserter.cpp +++ b/llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -68,9 +68,9 @@ class CFIInstrInserter : public MachineFunctionPass { struct MBBCFAInfo { MachineBasicBlock *MBB; /// Value of cfa offset valid at basic block entry. - int IncomingCFAOffset = -1; + int64_t IncomingCFAOffset = -1; /// Value of cfa offset valid at basic block exit. - int OutgoingCFAOffset = -1; + int64_t OutgoingCFAOffset = -1; /// Value of cfa register valid at basic block entry. unsigned IncomingCFARegister = 0; /// Value of cfa register valid at basic block exit. @@ -120,7 +120,7 @@ class CFIInstrInserter : public MachineFunctionPass { /// Return the cfa offset value that should be set at the beginning of a MBB /// if needed. The negated value is needed when creating CFI instructions that /// set absolute offset. - int getCorrectCFAOffset(MachineBasicBlock *MBB) { + int64_t getCorrectCFAOffset(MachineBasicBlock *MBB) { return MBBVector[MBB->getNumber()].IncomingCFAOffset; } @@ -175,7 +175,7 @@ void CFIInstrInserter::calculateCFAInfo(MachineFunction &MF) { void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) { // Outgoing cfa offset set by the block. - int SetOffset = MBBInfo.IncomingCFAOffset; + int64_t SetOffset = MBBInfo.IncomingCFAOffset; // Outgoing cfa register set by the block. unsigned SetRegister = MBBInfo.IncomingCFARegister; MachineFunction *MF = MBBInfo.MBB->getParent(); @@ -188,7 +188,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) { for (MachineInstr &MI : *MBBInfo.MBB) { if (MI.isCFIInstruction()) { std::optional CSRReg; - std::optional CSROffset; + std::optional CSROffset; unsigned CFIIndex = MI.getOperand(0).getCFIIndex(); const MCCFIInstruction &CFI = Instrs[CFIIndex]; switch (CFI.getOperation()) { diff --git a/llvm/lib/CodeGen/MachineFrameInfo.cpp b/llvm/lib/CodeGen/MachineFrameInfo.cpp index 853de4c88cae..e4b993850f73 100644 --- a/llvm/lib/CodeGen/MachineFrameInfo.cpp +++ b/llvm/lib/CodeGen/MachineFrameInfo.cpp @@ -197,7 +197,7 @@ void MachineFrameInfo::computeMaxCallFrameSize( for (MachineInstr &MI : MBB) { unsigned Opcode = MI.getOpcode(); if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) { - unsigned Size = TII.getFrameSize(MI); + uint64_t Size = TII.getFrameSize(MI); MaxCallFrameSize = std::max(MaxCallFrameSize, Size); if (FrameSDOps != nullptr) FrameSDOps->push_back(&MI); diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index eaf96ec5cbde..9771825ed875 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -366,8 +366,8 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) { return; // (Re-)Compute the MaxCallFrameSize. - [[maybe_unused]] uint32_t MaxCFSIn = - MFI.isMaxCallFrameSizeComputed() ? MFI.getMaxCallFrameSize() : UINT32_MAX; + [[maybe_unused]] uint64_t MaxCFSIn = + MFI.isMaxCallFrameSizeComputed() ? MFI.getMaxCallFrameSize() : UINT64_MAX; std::vector FrameSDOps; MFI.computeMaxCallFrameSize(MF, &FrameSDOps); assert(MFI.getMaxCallFrameSize() <= MaxCFSIn && diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index 2ee0c3eb27b9..9b8ec9bf2af0 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1298,8 +1298,8 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, namespace { class FrameEmitterImpl { - int CFAOffset = 0; - int InitialCFAOffset = 0; + int64_t CFAOffset = 0; + int64_t InitialCFAOffset = 0; bool IsEH; MCObjectStreamer &Streamer; @@ -1413,7 +1413,7 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) { if (!IsEH) Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg); - int Offset = Instr.getOffset(); + int64_t Offset = Instr.getOffset(); if (IsRelative) Offset -= CFAOffset; Offset = Offset / dataAlignmentFactor; diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index 30ef3680ae79..d83f7b5690ee 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -584,7 +584,7 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend { /// Encode compact unwind stack adjustment for frameless functions. /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h. /// The stack size always needs to be 16 byte aligned. - uint32_t encodeStackAdjustment(uint32_t StackSize) const { + uint64_t encodeStackAdjustment(uint64_t StackSize) const { return (StackSize / 16) << 12; } @@ -602,7 +602,7 @@ public: } /// Generate the compact unwind encoding from the CFI directives. - uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override { ArrayRef Instrs = FI->Instructions; if (Instrs.empty()) @@ -612,10 +612,10 @@ public: return CU::UNWIND_ARM64_MODE_DWARF; bool HasFP = false; - unsigned StackSize = 0; + uint64_t StackSize = 0; - uint32_t CompactUnwindEncoding = 0; - int CurOffset = 0; + uint64_t CompactUnwindEncoding = 0; + int64_t CurOffset = 0; for (size_t i = 0, e = Instrs.size(); i != e; ++i) { const MCCFIInstruction &Inst = Instrs[i]; diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 9b54dd4e4e61..a1012f3996e7 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1165,7 +1165,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, if (STI.splitFramePushPop(MF)) { unsigned DwarfReg = MRI->getDwarfRegNum( Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true); - unsigned Offset = MFI.getObjectOffset(FI); + uint64_t Offset = MFI.getObjectOffset(FI); unsigned CFIIndex = MF.addFrameInst( MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) @@ -1187,7 +1187,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, if ((Reg >= ARM::D0 && Reg <= ARM::D31) && (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())) { unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); - unsigned Offset = MFI.getObjectOffset(FI); + uint64_t Offset = MFI.getObjectOffset(FI); unsigned CFIIndex = MF.addFrameInst( MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 6cd4badb7704..9671f69bfd22 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -1148,7 +1148,7 @@ enum CompactUnwindEncodings { /// instructions. If the CFI instructions describe a frame that cannot be /// encoded in compact unwind, the method returns UNWIND_ARM_MODE_DWARF which /// tells the runtime to fallback and unwind using dwarf. -uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding( +uint64_t ARMAsmBackendDarwin::generateCompactUnwindEncoding( const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const { DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n"); // Only armv7k uses CFI based unwinding. diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h index ac0c9b101cae..9c958003ca75 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h @@ -34,7 +34,7 @@ public: /*Is64Bit=*/false, cantFail(MachO::getCPUType(TT)), Subtype); } - uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp index 232651132d6e..394456c13e68 100644 --- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -1660,7 +1660,7 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF, using SpillSlot = TargetFrameLowering::SpillSlot; unsigned NumFixed; - int MinOffset = 0; // CS offsets are negative. + int64_t MinOffset = 0; // CS offsets are negative. const SpillSlot *FixedSlots = getCalleeSavedSpillSlots(NumFixed); for (const SpillSlot *S = FixedSlots; S != FixedSlots+NumFixed; ++S) { if (!SRegs[S->Reg]) @@ -1679,7 +1679,7 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF, Register R = x; const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(R); unsigned Size = TRI->getSpillSize(*RC); - int Off = MinOffset - Size; + int64_t Off = MinOffset - Size; Align Alignment = std::min(TRI->getSpillAlign(*RC), getStackAlign()); Off &= -Alignment.value(); int FI = MFI.CreateFixedSpillStackObject(Size, Off); diff --git a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp index 176387d71fcb..6acbcf5cda24 100644 --- a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp +++ b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp @@ -294,7 +294,7 @@ void MSP430FrameLowering::emitEpilogue(MachineFunction &MF, if (!hasFP(MF)) { MBBI = FirstCSPop; - int64_t Offset = -CSSize - 2; + int64_t Offset = -(int64_t)CSSize - 2; // Mark callee-saved pop instruction. // Define the current CFA rule to use the provided offset. while (MBBI != MBB.end()) { diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 99dc9797f6df..23bff777df6e 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -1328,7 +1328,7 @@ public: /// Implementation of algorithm to generate the compact unwind encoding /// for the CFI instructions. - uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override { ArrayRef Instrs = FI->Instructions; if (Instrs.empty()) return 0; @@ -1343,13 +1343,13 @@ public: bool HasFP = false; // Encode that we are using EBP/RBP as the frame pointer. - uint32_t CompactUnwindEncoding = 0; + uint64_t CompactUnwindEncoding = 0; unsigned SubtractInstrIdx = Is64Bit ? 3 : 2; unsigned InstrOffset = 0; unsigned StackAdjust = 0; - unsigned StackSize = 0; - int MinAbsOffset = std::numeric_limits::max(); + uint64_t StackSize = 0; + int64_t MinAbsOffset = std::numeric_limits::max(); for (const MCCFIInstruction &Inst : Instrs) { switch (Inst.getOperation()) { @@ -1376,7 +1376,7 @@ public: memset(SavedRegs, 0, sizeof(SavedRegs)); StackAdjust = 0; SavedRegIdx = 0; - MinAbsOffset = std::numeric_limits::max(); + MinAbsOffset = std::numeric_limits::max(); InstrOffset += MoveInstrSize; break; } @@ -1419,7 +1419,8 @@ public: unsigned Reg = *MRI.getLLVMRegNum(Inst.getRegister(), true); SavedRegs[SavedRegIdx++] = Reg; StackAdjust += OffsetSize; - MinAbsOffset = std::min(MinAbsOffset, abs(Inst.getOffset())); + MinAbsOffset = + std::min(MinAbsOffset, std::abs(Inst.getOffset())); InstrOffset += PushInstrSize(Reg); break; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 92a14226a0dc..1df2b86349a2 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -358,7 +358,8 @@ private: void emitImmediate(const MCOperand &Disp, SMLoc Loc, unsigned ImmSize, MCFixupKind FixupKind, uint64_t StartByte, SmallVectorImpl &CB, - SmallVectorImpl &Fixups, int ImmOffset = 0) const; + SmallVectorImpl &Fixups, + int64_t ImmOffset = 0) const; void emitRegModRMByte(const MCOperand &ModRMReg, unsigned RegOpcodeFld, SmallVectorImpl &CB) const; @@ -412,7 +413,8 @@ static void emitConstant(uint64_t Val, unsigned Size, /// Determine if this immediate can fit in a disp8 or a compressed disp8 for /// EVEX instructions. \p will be set to the value to pass to the ImmOffset /// parameter of emitImmediate. -static bool isDispOrCDisp8(uint64_t TSFlags, int Value, int &ImmOffset) { +static bool isDispOrCDisp8(uint64_t TSFlags, int64_t Value, + int64_t &ImmOffset) { bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX; unsigned CD8_Scale = @@ -425,7 +427,7 @@ static bool isDispOrCDisp8(uint64_t TSFlags, int Value, int &ImmOffset) { if (Value & (CD8_Scale - 1)) // Unaligned offset return false; - int CDisp8 = Value / static_cast(CD8_Scale); + int64_t CDisp8 = Value / static_cast(CD8_Scale); if (!isInt<8>(CDisp8)) return false; @@ -518,7 +520,7 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc, uint64_t StartByte, SmallVectorImpl &CB, SmallVectorImpl &Fixups, - int ImmOffset) const { + int64_t ImmOffset) const { const MCExpr *Expr = nullptr; if (DispOp.isImm()) { // If this is a simple integer displacement that doesn't require a @@ -799,7 +801,7 @@ void X86MCCodeEmitter::emitMemModRMByte( // This also handles the 0 displacement for [EBP], [R13], [R21] or [R29]. We // can't use disp8 if the {disp32} pseudo prefix is present. if (Disp.isImm() && AllowDisp8) { - int ImmOffset = 0; + int64_t ImmOffset = 0; if (isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) { emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), CB); emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, CB, Fixups, @@ -826,7 +828,7 @@ void X86MCCodeEmitter::emitMemModRMByte( bool ForceDisp32 = false; bool ForceDisp8 = false; - int ImmOffset = 0; + int64_t ImmOffset = 0; if (BaseReg == 0) { // If there is no base register, we emit the special case SIB byte with // MOD=0, BASE=5, to JUST get the index, scale, and displacement. diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index d914e1b61ab0..3e44ed621fdf 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -380,9 +380,9 @@ MachineInstrBuilder X86FrameLowering::BuildStackAdjustment( return MI; } -int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - bool doMergeWithPrevious) const { +int64_t X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + bool doMergeWithPrevious) const { if ((doMergeWithPrevious && MBBI == MBB.begin()) || (!doMergeWithPrevious && MBBI == MBB.end())) return 0; @@ -405,7 +405,7 @@ int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, PI = std::prev(PI); unsigned Opc = PI->getOpcode(); - int Offset = 0; + int64_t Offset = 0; if ((Opc == X86::ADD64ri32 || Opc == X86::ADD32ri) && PI->getOperand(0).getReg() == StackPtr) { @@ -473,7 +473,7 @@ void X86FrameLowering::emitCalleeSavedFrameMovesFullCFA( : FramePtr; unsigned DwarfReg = MRI->getDwarfRegNum(MachineFramePtr, true); // Offset = space for return address + size of the frame pointer itself. - unsigned Offset = (Is64Bit ? 8 : 4) + (Uses64BitFramePtr ? 8 : 4); + int64_t Offset = (Is64Bit ? 8 : 4) + (Uses64BitFramePtr ? 8 : 4); BuildCFI(MBB, MBBI, DebugLoc{}, MCCFIInstruction::createOffset(nullptr, DwarfReg, -Offset)); emitCalleeSavedFrameMoves(MBB, MBBI, DebugLoc{}, true); @@ -1881,7 +1881,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // For EH funclets, only allocate enough space for outgoing calls. Save the // NumBytes value that we would've used for the parent frame. - unsigned ParentFrameNumBytes = NumBytes; + uint64_t ParentFrameNumBytes = NumBytes; if (IsFunclet) NumBytes = getWinEHFuncletFrameSize(MF); @@ -2430,7 +2430,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (HasFP) { if (X86FI->hasSwiftAsyncContext()) { // Discard the context. - int Offset = 16 + mergeSPUpdates(MBB, MBBI, true); + int64_t Offset = 16 + mergeSPUpdates(MBB, MBBI, true); emitSPUpdate(MBB, MBBI, DL, Offset, /*InEpilogue*/ true); } // Pop EBP. @@ -2562,7 +2562,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (!HasFP && NeedsDwarfCFI) { MBBI = FirstCSPop; - int64_t Offset = -CSSize - SlotSize; + int64_t Offset = -(int64_t)CSSize - SlotSize; // Mark callee-saved pop instruction. // Define the current CFA rule to use the provided offset. while (MBBI != MBB.end()) { @@ -2591,7 +2591,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (Terminator == MBB.end() || !isTailCallOpcode(Terminator->getOpcode())) { // Add the return addr area delta back since we are not tail calling. - int Offset = -1 * X86FI->getTCReturnAddrDelta(); + int64_t Offset = -1 * X86FI->getTCReturnAddrDelta(); assert(Offset >= 0 && "TCDelta should never be positive"); if (Offset) { // Check for possible merge with preceding ADD instruction. @@ -2625,7 +2625,7 @@ StackOffset X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, // object. // We need to factor in additional offsets applied during the prologue to the // frame, base, and stack pointer depending on which is used. - int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea(); + int64_t Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea(); const X86MachineFunctionInfo *X86FI = MF.getInfo(); unsigned CSSize = X86FI->getCalleeSavedFrameSize(); uint64_t StackSize = MFI.getStackSize(); @@ -3919,7 +3919,7 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( // FIXME: Don't set FrameSetup flag in catchret case. int FI = FuncInfo.EHRegNodeFrameIndex; - int EHRegSize = MFI.getObjectSize(FI); + int64_t EHRegSize = MFI.getObjectSize(FI); if (RestoreSP) { // MOV32rm -EHRegSize(%ebp), %esp @@ -3929,8 +3929,8 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( } Register UsedReg; - int EHRegOffset = getFrameIndexReference(MF, FI, UsedReg).getFixed(); - int EndOffset = -EHRegOffset - EHRegSize; + int64_t EHRegOffset = getFrameIndexReference(MF, FI, UsedReg).getFixed(); + int64_t EndOffset = -EHRegOffset - EHRegSize; FuncInfo.EHRegNodeEndOffset = EndOffset; if (UsedReg == FramePtr) { @@ -3951,7 +3951,7 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( .setMIFlag(MachineInstr::FrameSetup); // MOV32rm SavedEBPOffset(%esi), %ebp assert(X86FI->getHasSEHFramePtrSave()); - int Offset = + int64_t Offset = getFrameIndexReference(MF, X86FI->getSEHFramePtrSaveIndex(), UsedReg) .getFixed(); assert(UsedReg == BasePtr); diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h index 2dc9ecc6109d..49580b31d39c 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.h +++ b/llvm/lib/Target/X86/X86FrameLowering.h @@ -137,8 +137,9 @@ public: /// it is an ADD/SUB/LEA instruction it is deleted argument and the /// stack adjustment is returned as a positive value for ADD/LEA and /// a negative for SUB. - int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, - bool doMergeWithPrevious) const; + int64_t mergeSPUpdates(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + bool doMergeWithPrevious) const; /// Emit a series of instructions to increment / decrement the stack /// pointer by a constant value. diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index be0cf1596d0d..57f645462089 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -893,7 +893,7 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); // Determine base register and offset. - int FIOffset; + int64_t FIOffset; Register BasePtr; if (MI.isReturn()) { assert((!hasStackRealignment(MF) || @@ -946,9 +946,11 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, if (MI.getOperand(FIOperandNum+3).isImm()) { // Offset is a 32-bit integer. int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm()); - int Offset = FIOffset + Imm; - assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) && - "Requesting 64-bit offset in 32-bit immediate!"); + int64_t Offset = FIOffset + Imm; + if (!Is64Bit) { + assert(isInt<32>((long long)FIOffset + Imm) && + "Requesting 64-bit offset in 32-bit immediate!"); + } if (Offset != 0 || !tryOptimizeLEAtoMOV(II)) MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset); } else { diff --git a/llvm/test/CodeGen/PowerPC/huge-frame-size.ll b/llvm/test/CodeGen/PowerPC/huge-frame-size.ll index f1039df6f549..78bdac021ac8 100644 --- a/llvm/test/CodeGen/PowerPC/huge-frame-size.ll +++ b/llvm/test/CodeGen/PowerPC/huge-frame-size.ll @@ -18,7 +18,7 @@ define void @foo(i8 %x) { ; CHECK-LE-NEXT: oris 0, 0, 65535 ; CHECK-LE-NEXT: ori 0, 0, 65504 ; CHECK-LE-NEXT: stdux 1, 1, 0 -; CHECK-LE-NEXT: .cfi_def_cfa_offset 32 +; CHECK-LE-NEXT: .cfi_def_cfa_offset 4294967328 ; CHECK-LE-NEXT: li 4, 1 ; CHECK-LE-NEXT: addi 5, 1, 32 ; CHECK-LE-NEXT: stb 3, 32(1) diff --git a/llvm/test/CodeGen/X86/huge-stack.ll b/llvm/test/CodeGen/X86/huge-stack.ll new file mode 100644 index 000000000000..4596c50382a0 --- /dev/null +++ b/llvm/test/CodeGen/X86/huge-stack.ll @@ -0,0 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --no_x86_scrub_sp --version 4 +; RUN: llc -O0 -mtriple=x86_64 < %s | FileCheck %s --check-prefix=CHECK +%large = type [4294967295 x i8] + +define void @foo() unnamed_addr #0 { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: +; CHECK-NEXT: movabsq $8589934462, %rax # imm = 0x1FFFFFF7E +; CHECK-NEXT: subq %rax, %rsp +; CHECK-NEXT: .cfi_def_cfa_offset 8589934470 +; CHECK-NEXT: movb $42, 4294967167(%rsp) +; CHECK-NEXT: movb $43, -128(%rsp) +; CHECK-NEXT: movabsq $8589934462, %rax # imm = 0x1FFFFFF7E +; CHECK-NEXT: addq %rax, %rsp +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq + %1 = alloca %large, align 1 + %2 = alloca %large, align 1 + %3 = getelementptr inbounds %large, ptr %1, i64 0, i64 0 + store i8 42, ptr %3, align 1 + %4 = getelementptr inbounds %large, ptr %2, i64 0, i64 0 + store i8 43, ptr %4, align 1 + ret void +} -- GitLab From 13b653ab112736b92cd7f8ef249ced2b148ee7f4 Mon Sep 17 00:00:00 2001 From: Brandon Wu Date: Wed, 27 Mar 2024 23:22:01 +0800 Subject: [PATCH 069/541] [clang][RISCV] Enable RVV with function attribute __attribute__((target("arch=+v"))) (#83674) It is currently not possible to use "RVV type" and "RVV intrinsics" if the "zve32x" is not enabled globally. However in some cases we may want to use them only in some functions, for instance: ``` #include __attribute__((target("+zve32x"))) vint32m1_t rvv_add(vint32m1_t v1, vint32m1_t v2, size_t vl) { return __riscv_vadd(v1, v2, vl); } int other_add(int i1, int i2) { return i1 + i2; } ``` , it is supposed to be compilable even the vector is not specified, e.g. `clang -target riscv64 -march=rv64gc -S test.c`. --- clang/include/clang/Sema/Sema.h | 3 +- clang/lib/Sema/Sema.cpp | 7 +- clang/lib/Sema/SemaChecking.cpp | 70 +++---------------- clang/lib/Sema/SemaDecl.cpp | 9 ++- .../RISCV/riscv-func-attr-target-err.c | 22 ++++++ .../CodeGen/RISCV/riscv-func-attr-target.c | 33 +++++++++ .../RISCV/rvb-intrinsics/riscv32-zbb-error.c | 4 +- .../RISCV/rvb-intrinsics/riscv64-zbkb-error.c | 12 ++-- .../rvv-intrinsics-handcrafted/rvv-error.c | 2 +- clang/utils/TableGen/RISCVVEmitter.cpp | 4 -- 10 files changed, 85 insertions(+), 81 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5ecd2f9eb288..3a1abd4c7892 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2234,7 +2234,8 @@ private: bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); - void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D); + void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap &FeatureMap); bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index b55f433a8be7..72393bea6205 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -2065,8 +2065,11 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } - if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType()) - checkRVVTypeSupport(Ty, Loc, D); + if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType() && FD) { + llvm::StringMap CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + checkRVVTypeSupport(Ty, Loc, D, CallerFeatureMap); + } // Don't allow SVE types in functions without a SVE target. if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 084495813309..447e73686b4f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5760,57 +5760,6 @@ static bool CheckInvalidVLENandLMUL(const TargetInfo &TI, CallExpr *TheCall, bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { - // CodeGenFunction can also detect this, but this gives a better error - // message. - bool FeatureMissing = false; - SmallVector ReqFeatures; - StringRef Features = Context.BuiltinInfo.getRequiredFeatures(BuiltinID); - Features.split(ReqFeatures, ',', -1, false); - - // Check if each required feature is included - for (StringRef F : ReqFeatures) { - SmallVector ReqOpFeatures; - F.split(ReqOpFeatures, '|'); - - if (llvm::none_of(ReqOpFeatures, - [&TI](StringRef OF) { return TI.hasFeature(OF); })) { - std::string FeatureStrs; - bool IsExtension = true; - for (StringRef OF : ReqOpFeatures) { - // If the feature is 64bit, alter the string so it will print better in - // the diagnostic. - if (OF == "64bit") { - assert(ReqOpFeatures.size() == 1 && "Expected '64bit' to be alone"); - OF = "RV64"; - IsExtension = false; - } - if (OF == "32bit") { - assert(ReqOpFeatures.size() == 1 && "Expected '32bit' to be alone"); - OF = "RV32"; - IsExtension = false; - } - - // Convert features like "zbr" and "experimental-zbr" to "Zbr". - OF.consume_front("experimental-"); - std::string FeatureStr = OF.str(); - FeatureStr[0] = std::toupper(FeatureStr[0]); - // Combine strings. - FeatureStrs += FeatureStrs.empty() ? "" : ", "; - FeatureStrs += "'"; - FeatureStrs += FeatureStr; - FeatureStrs += "'"; - } - // Error message - FeatureMissing = true; - Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension) - << IsExtension - << TheCall->getSourceRange() << StringRef(FeatureStrs); - } - } - - if (FeatureMissing) - return true; - // vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx, // vsmul.vv, vsmul.vx are not included for EEW=64 in Zve64*. switch (BuiltinID) { @@ -6714,36 +6663,35 @@ bool Sema::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, return false; } -void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D) { - const TargetInfo &TI = Context.getTargetInfo(); - +void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap &FeatureMap) { ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty->castAs()); unsigned EltSize = Context.getTypeSize(Info.ElementType); unsigned MinElts = Info.EC.getKnownMinValue(); if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Double) && - !TI.hasFeature("zve64d")) + !FeatureMap.lookup("zve64d")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64d"; // (ELEN, LMUL) pairs of (8, mf8), (16, mf4), (32, mf2), (64, m1) requires at // least zve64x else if (((EltSize == 64 && Info.ElementType->isIntegerType()) || MinElts == 1) && - !TI.hasFeature("zve64x")) + !FeatureMap.lookup("zve64x")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64x"; - else if (Info.ElementType->isFloat16Type() && !TI.hasFeature("zvfh") && - !TI.hasFeature("zvfhmin")) + else if (Info.ElementType->isFloat16Type() && !FeatureMap.lookup("zvfh") && + !FeatureMap.lookup("zvfhmin")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfh or zvfhmin"; else if (Info.ElementType->isBFloat16Type() && - !TI.hasFeature("experimental-zvfbfmin")) + !FeatureMap.lookup("experimental-zvfbfmin")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfbfmin"; else if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Float) && - !TI.hasFeature("zve32f")) + !FeatureMap.lookup("zve32f")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32f"; // Given that caller already checked isRVVType() before calling this function, // if we don't have at least zve32x supported, then we need to emit error. - else if (!TI.hasFeature("zve32x")) + else if (!FeatureMap.lookup("zve32x")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32x"; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 66aad2592cb3..8b44d24f5273 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8962,8 +8962,13 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } - if (T->isRVVSizelessBuiltinType()) - checkRVVTypeSupport(T, NewVD->getLocation(), cast(CurContext)); + if (T->isRVVSizelessBuiltinType() && isa(CurContext)) { + const FunctionDecl *FD = cast(CurContext); + llvm::StringMap CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + checkRVVTypeSupport(T, NewVD->getLocation(), cast(CurContext), + CallerFeatureMap); + } } /// Perform semantic checking on a newly-created variable diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c index 35d6973818d0..b303d71304bf 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c @@ -2,6 +2,28 @@ // RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \ // RUN: -emit-llvm %s 2>&1 | FileCheck %s +#include + +void test_builtin() { +// CHECK: error: '__builtin_rvv_vsetvli' needs target feature zve32x + __riscv_vsetvl_e8m8(1); +} + +void test_rvv_i32_type() { +// CHECK: error: RISC-V type 'vint32m1_t' (aka '__rvv_int32m1_t') requires the 'zve32x' extension + vint32m1_t v; +} + +void test_rvv_f32_type() { +// CHECK: error: RISC-V type 'vfloat32m1_t' (aka '__rvv_float32m1_t') requires the 'zve32f' extension + vfloat32m1_t v; +} + +void test_rvv_f64_type() { +// CHECK: error: RISC-V type 'vfloat64m1_t' (aka '__rvv_float64m1_t') requires the 'zve64d' extension + vfloat64m1_t v; +} + // CHECK: error: duplicate 'arch=' in the 'target' attribute string; __attribute__((target("arch=rv64gc;arch=rv64gc_zbb"))) void testMultiArchSelectLast() {} // CHECK: error: duplicate 'cpu=' in the 'target' attribute string; diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c index f216eaf735b4..1f8682179ea8 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c @@ -4,6 +4,8 @@ // RUN: -target-feature -relax -target-feature -zfa \ // RUN: -emit-llvm %s -o - | FileCheck %s +#include + // CHECK-LABEL: define dso_local void @testDefault // CHECK-SAME: () #0 { void testDefault() {} @@ -35,6 +37,34 @@ testAttrFullArchAndAttrCpu() {} // CHECK-SAME: () #8 { __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} +__attribute__((target("arch=+zve32x"))) +void test_builtin_w_zve32x() { +// CHECK-LABEL: test_builtin_w_zve32x +// CHECK-SAME: #9 + __riscv_vsetvl_e8m8(1); +} + +__attribute__((target("arch=+zve32x"))) +void test_rvv_i32_type_w_zve32x() { +// CHECK-LABEL: test_rvv_i32_type_w_zve32x +// CHECK-SAME: #9 + vint32m1_t v; +} + +__attribute__((target("arch=+zve32f"))) +void test_rvv_f32_type_w_zve32f() { +// CHECK-LABEL: test_rvv_f32_type_w_zve32f +// CHECK-SAME: #11 + vfloat32m1_t v; +} + +__attribute__((target("arch=+zve64d"))) +void test_rvv_f64_type_w_zve64d() { +// CHECK-LABEL: test_rvv_f64_type_w_zve64d +// CHECK-SAME: #12 + vfloat64m1_t v; +} + //. // CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" } // CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="generic-rv64" } @@ -46,3 +76,6 @@ __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} // CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" } // CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" } // CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" } +// CHECK: attributes #9 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zicsr,+zifencei,+zve32x,+zvl32b,-relax,-zbb,-zfa" } +// CHECK: attributes #11 = { {{.*}}"target-features"="+64bit,+a,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zvl32b,-relax,-zbb,-zfa" } +// CHECK: attributes #12 = { {{.*}}"target-features"="+64bit,+a,+d,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl32b,+zvl64b,-relax,-zbb,-zfa" } diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c index ecf090a128aa..bad68504fab0 100644 --- a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -verify %s -o - +// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -S -verify %s -o - unsigned int orc_b_64(unsigned int a) { - return __builtin_riscv_orc_b_64(a); // expected-error {{builtin requires: 'RV64'}} + return __builtin_riscv_orc_b_64(a); // expected-error {{'__builtin_riscv_orc_b_64' needs target feature zbb,64bit}} } diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c index d2e3e76043ae..a256bf75b031 100644 --- a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c @@ -1,14 +1,10 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -verify %s -o - +// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -S -verify %s -o - #include -uint32_t zip(uint32_t rs1) +uint32_t zip_unzip(uint32_t rs1) { - return __builtin_riscv_zip_32(rs1); // expected-error {{builtin requires: 'RV32'}} -} - -uint32_t unzip(uint32_t rs1) -{ - return __builtin_riscv_unzip_32(rs1); // expected-error {{builtin requires: 'RV32'}} + (void)__builtin_riscv_zip_32(rs1); // expected-error {{'__builtin_riscv_zip_32' needs target feature zbkb,32bit}} + return __builtin_riscv_unzip_32(rs1); // expected-error {{'__builtin_riscv_unzip_32' needs target feature zbkb,32bit}} } diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c index 6ec9b0579976..ecb6c5f27025 100644 --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c @@ -11,7 +11,7 @@ // CHECK-RV64V-NEXT: ret i32 [[CONV]] // -// CHECK-RV64-ERR: error: builtin requires at least one of the following extensions: 'Zve32x' +// CHECK-RV64-ERR: error: '__builtin_rvv_vsetvli' needs target feature zve32x int test() { return __builtin_rvv_vsetvli(1, 0, 0); diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp index 8513174c88bf..5e41ef9f9d26 100644 --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -334,10 +334,6 @@ void RVVEmitter::createHeader(raw_ostream &OS) { OS << "#include \n"; OS << "#include \n\n"; - OS << "#ifndef __riscv_vector\n"; - OS << "#error \"Vector intrinsics require the vector extension.\"\n"; - OS << "#endif\n\n"; - OS << "#ifdef __cplusplus\n"; OS << "extern \"C\" {\n"; OS << "#endif\n\n"; -- GitLab From 51f7b262425959d4e2bd6bc79fed283586d0472e Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Wed, 27 Mar 2024 08:22:51 -0700 Subject: [PATCH 070/541] [libc][support][UInt] implement 128b math helpers (#86531) Flush out the remaining UInt<128> support and add test coverage. We could have used cpp::popcount in the implementation of UInt::has_single_bit, but has_single_bit has a perhaps useful early return. --- libc/src/__support/CPP/bit.h | 10 +++- libc/src/__support/UInt.h | 54 ++++++++++++++++++++ libc/test/src/__support/CPP/bit_test.cpp | 9 +--- libc/test/src/__support/math_extras_test.cpp | 4 +- 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index 3f2fbec94405..526c499adc37 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -242,6 +242,14 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) { /// Count number of 1's aka population count or Hamming weight. /// /// Only unsigned integral types are allowed. +// clang-19+, gcc-14+ +#if __has_builtin(__builtin_popcountg) +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +popcount(T value) { + return __builtin_popcountg(value); +} +#else // !__has_builtin(__builtin_popcountg) template [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> popcount(T value) { @@ -261,7 +269,7 @@ ADD_SPECIALIZATION(unsigned short, __builtin_popcount) ADD_SPECIALIZATION(unsigned, __builtin_popcount) ADD_SPECIALIZATION(unsigned long, __builtin_popcountl) ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) -// TODO: 128b specializations? +#endif // __builtin_popcountg #undef ADD_SPECIALIZATION } // namespace LIBC_NAMESPACE::cpp diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index df01e081e3c1..282efdba1c5f 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -1082,6 +1082,17 @@ bit_cast(const UInt &from) { return cpp::bit_cast(from.val); } +// Specialization of cpp::popcount ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +popcount(T value) { + int bits = 0; + for (auto word : value.val) + if (word) + bits += popcount(word); + return bits; +} + // Specialization of cpp::has_single_bit ('bit.h') for BigInt. template [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, bool> @@ -1218,6 +1229,49 @@ LIBC_INLINE constexpr cpp::enable_if_t, T> mask_leading_ones() { return out; } +// Specialization of count_zeros ('math_extras.h') for BigInt. +template +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t, int> +count_zeros(T value) { + return cpp::popcount(~value); +} + +// Specialization of first_leading_zero ('math_extras.h') for BigInt. +template +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t, int> +first_leading_zero(T value) { + return value == cpp::numeric_limits::max() ? 0 + : cpp::countl_one(value) + 1; +} + +// Specialization of first_leading_one ('math_extras.h') for BigInt. +template +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t, int> +first_leading_one(T value) { + return first_leading_zero(~value); +} + +// Specialization of first_trailing_zero ('math_extras.h') for BigInt. +template +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t, int> +first_trailing_zero(T value) { + return value == cpp::numeric_limits::max() ? 0 + : cpp::countr_zero(~value) + 1; +} + +// Specialization of first_trailing_one ('math_extras.h') for BigInt. +template +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t, int> +first_trailing_one(T value) { + return value == cpp::numeric_limits::max() ? 0 + : cpp::countr_zero(value) + 1; +} + } // namespace LIBC_NAMESPACE #endif // LLVM_LIBC_SRC___SUPPORT_UINT_H diff --git a/libc/test/src/__support/CPP/bit_test.cpp b/libc/test/src/__support/CPP/bit_test.cpp index cee5b90c8f4b..875b47e6a198 100644 --- a/libc/test/src/__support/CPP/bit_test.cpp +++ b/libc/test/src/__support/CPP/bit_test.cpp @@ -15,13 +15,6 @@ namespace LIBC_NAMESPACE::cpp { -using UnsignedTypesNoBigInt = testing::TypeList< -#if defined(LIBC_TYPES_HAS_INT128) - __uint128_t, -#endif // LIBC_TYPES_HAS_INT128 - unsigned char, unsigned short, unsigned int, unsigned long, - unsigned long long>; - using UnsignedTypes = testing::TypeList< #if defined(LIBC_TYPES_HAS_INT128) __uint128_t, @@ -228,7 +221,7 @@ TEST(LlvmLibcBitTest, Rotr) { rotr(0x12345678deadbeefULL, -19)); } -TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypes) { EXPECT_EQ(popcount(T(0)), 0); for (int i = 0; i != cpp::numeric_limits::digits; ++i) EXPECT_EQ(popcount(cpp::numeric_limits::max() >> i), diff --git a/libc/test/src/__support/math_extras_test.cpp b/libc/test/src/__support/math_extras_test.cpp index e642248881a4..e88b3e1d6b68 100644 --- a/libc/test/src/__support/math_extras_test.cpp +++ b/libc/test/src/__support/math_extras_test.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/UInt128.h" // UInt128 +#include "src/__support/UInt128.h" // UInt<128> #include "src/__support/integer_literals.h" #include "src/__support/math_extras.h" #include "test/UnitTest/Test.h" @@ -19,7 +19,7 @@ using UnsignedTypesNoBigInt = testing::TypeList< __uint128_t, #endif // LIBC_TYPES_HAS_INT128 unsigned char, unsigned short, unsigned int, unsigned long, - unsigned long long>; + unsigned long long, UInt<128>>; TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) { EXPECT_EQ(0_u8, (mask_leading_ones())); -- GitLab From aa2c14de1adcd265bf0c0fb44f97b5d6c1c38710 Mon Sep 17 00:00:00 2001 From: Terry Wilmarth Date: Wed, 27 Mar 2024 11:27:28 -0400 Subject: [PATCH 071/541] [OpenMP] Close up permissions on /tmp files (#85469) The SHM or /tmp files that might be created during library registration don't need to have such open permissions, so this change fixes that. --- openmp/runtime/src/kmp_runtime.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index a60bdb968371..a242049286a7 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -6752,11 +6752,11 @@ void __kmp_register_library_startup(void) { int fd1 = -1; shm_name = __kmp_str_format("/%s", name); int shm_preexist = 0; - fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666); + fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0600); if ((fd1 == -1) && (errno == EEXIST)) { // file didn't open because it already exists. // try opening existing file - fd1 = shm_open(shm_name, O_RDWR, 0666); + fd1 = shm_open(shm_name, O_RDWR, 0600); if (fd1 == -1) { // file didn't open KMP_WARNING(FunctionError, "Can't open SHM"); __kmp_shm_available = false; @@ -6800,11 +6800,11 @@ void __kmp_register_library_startup(void) { int fd1 = -1; temp_reg_status_file_name = __kmp_str_format("/tmp/%s", name); int tmp_preexist = 0; - fd1 = open(temp_reg_status_file_name, O_CREAT | O_EXCL | O_RDWR, 0666); + fd1 = open(temp_reg_status_file_name, O_CREAT | O_EXCL | O_RDWR, 0600); if ((fd1 == -1) && (errno == EEXIST)) { // file didn't open because it already exists. // try opening existing file - fd1 = open(temp_reg_status_file_name, O_RDWR, 0666); + fd1 = open(temp_reg_status_file_name, O_RDWR, 0600); if (fd1 == -1) { // file didn't open if (fd1 == -1) { KMP_WARNING(FunctionError, "Can't open TEMP"); __kmp_tmp_available = false; @@ -6944,7 +6944,7 @@ void __kmp_unregister_library(void) { int fd1; if (__kmp_shm_available) { shm_name = __kmp_str_format("/%s", name); - fd1 = shm_open(shm_name, O_RDONLY, 0666); + fd1 = shm_open(shm_name, O_RDONLY, 0600); if (fd1 != -1) { // File opened successfully char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0); if (data1 != MAP_FAILED) { -- GitLab From 009f88fc0e3a036be97ef7b222b90af342bae0b7 Mon Sep 17 00:00:00 2001 From: Yusra Syeda <99052248+ysyeda@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:31:21 -0400 Subject: [PATCH 072/541] [SystemZ][z/OS] TXT records in the GOFF reader (#74526) This PR adds handling for TXT records in the GOFF reader. --------- Authored-by: Yusra Syeda --- llvm/include/llvm/Object/GOFF.h | 20 +++ llvm/include/llvm/Object/GOFFObjectFile.h | 56 +++++-- llvm/lib/Object/GOFFObjectFile.cpp | 167 +++++++++++++++++++ llvm/unittests/Object/GOFFObjectFileTest.cpp | 97 +++++++++++ 4 files changed, 326 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/Object/GOFF.h b/llvm/include/llvm/Object/GOFF.h index 91762457ae05..9fb8876e893d 100644 --- a/llvm/include/llvm/Object/GOFF.h +++ b/llvm/include/llvm/Object/GOFF.h @@ -73,6 +73,26 @@ protected: } }; +class TXTRecord : public Record { +public: + /// \brief Maximum length of data; any more must go in continuation. + static const uint8_t TXTMaxDataLength = 56; + + static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); + + static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) { + get(Record, 4, EsdId); + } + + static void getOffset(const uint8_t *Record, uint32_t &Offset) { + get(Record, 12, Offset); + } + + static void getDataLength(const uint8_t *Record, uint16_t &Length) { + get(Record, 22, Length); + } +}; + class HDRRecord : public Record { public: static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); diff --git a/llvm/include/llvm/Object/GOFFObjectFile.h b/llvm/include/llvm/Object/GOFFObjectFile.h index 7e1ceb95f667..6871641e97ec 100644 --- a/llvm/include/llvm/Object/GOFFObjectFile.h +++ b/llvm/include/llvm/Object/GOFFObjectFile.h @@ -29,7 +29,10 @@ namespace llvm { namespace object { class GOFFObjectFile : public ObjectFile { + friend class GOFFSymbolRef; + IndexedMap EsdPtrs; // Indexed by EsdId. + SmallVector TextPtrs; mutable DenseMap>> EsdNamesCache; @@ -38,7 +41,7 @@ class GOFFObjectFile : public ObjectFile { // (EDID, 0) code, r/o data section // (EDID,PRID) r/w data section SmallVector SectionList; - mutable DenseMap SectionDataCache; + mutable DenseMap> SectionDataCache; public: Expected getSymbolName(SymbolRef Symbol) const; @@ -66,6 +69,10 @@ public: return true; } + bool isSectionNoLoad(DataRefImpl Sec) const; + bool isSectionReadOnlyData(DataRefImpl Sec) const; + bool isSectionZeroInit(DataRefImpl Sec) const; + private: // SymbolRef. Expected getSymbolName(DataRefImpl Symb) const override; @@ -75,27 +82,24 @@ private: Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; + uint64_t getSymbolSize(DataRefImpl Symb) const; const uint8_t *getSymbolEsdRecord(DataRefImpl Symb) const; bool isSymbolUnresolved(DataRefImpl Symb) const; bool isSymbolIndirect(DataRefImpl Symb) const; // SectionRef. - void moveSectionNext(DataRefImpl &Sec) const override {} - virtual Expected getSectionName(DataRefImpl Sec) const override { - return StringRef(); - } - uint64_t getSectionAddress(DataRefImpl Sec) const override { return 0; } - uint64_t getSectionSize(DataRefImpl Sec) const override { return 0; } + void moveSectionNext(DataRefImpl &Sec) const override; + virtual Expected getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; virtual Expected> - getSectionContents(DataRefImpl Sec) const override { - return ArrayRef(); - } - uint64_t getSectionIndex(DataRefImpl Sec) const override { return 0; } - uint64_t getSectionAlignment(DataRefImpl Sec) const override { return 0; } + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override { return Sec.d.a; } + uint64_t getSectionAlignment(DataRefImpl Sec) const override; bool isSectionCompressed(DataRefImpl Sec) const override { return false; } - bool isSectionText(DataRefImpl Sec) const override { return false; } - bool isSectionData(DataRefImpl Sec) const override { return false; } + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override { return false; } bool isSectionVirtual(DataRefImpl Sec) const override { return false; } relocation_iterator section_rel_begin(DataRefImpl Sec) const override { @@ -109,6 +113,7 @@ private: const uint8_t *getSectionPrEsdRecord(DataRefImpl &Sec) const; const uint8_t *getSectionEdEsdRecord(uint32_t SectionIndex) const; const uint8_t *getSectionPrEsdRecord(uint32_t SectionIndex) const; + uint32_t getSectionDefEsdId(DataRefImpl &Sec) const; // RelocationRef. void moveRelocationNext(DataRefImpl &Rel) const override {} @@ -122,6 +127,29 @@ private: SmallVectorImpl &Result) const override {} }; +class GOFFSymbolRef : public SymbolRef { +public: + GOFFSymbolRef(const SymbolRef &B) : SymbolRef(B) { + assert(isa(SymbolRef::getObject())); + } + + const GOFFObjectFile *getObject() const { + return cast(BasicSymbolRef::getObject()); + } + + Expected getSymbolGOFFFlags() const { + return getObject()->getSymbolFlags(getRawDataRefImpl()); + } + + Expected getSymbolGOFFType() const { + return getObject()->getSymbolType(getRawDataRefImpl()); + } + + uint64_t getSize() const { + return getObject()->getSymbolSize(getRawDataRefImpl()); + } +}; + } // namespace object } // namespace llvm diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp index 76a13559ebfe..6b48d464dc3e 100644 --- a/llvm/lib/Object/GOFFObjectFile.cpp +++ b/llvm/lib/Object/GOFFObjectFile.cpp @@ -168,6 +168,11 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n"); break; } + case GOFF::RT_TXT: + // Save TXT records. + TextPtrs.emplace_back(I); + LLVM_DEBUG(dbgs() << " -- TXT\n"); + break; case GOFF::RT_END: LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n"); break; @@ -364,6 +369,13 @@ GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { std::to_string(SymEdId)); } +uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { + const uint8_t *Record = getSymbolEsdRecord(Symb); + uint32_t Length; + ESDRecord::getLength(Record, Length); + return Length; +} + const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const { SectionEntryImpl EsdIds = SectionList[Sec.d.a]; const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a]; @@ -394,6 +406,154 @@ GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const { return EsdRecord; } +uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + uint32_t Length; + ESDRecord::getLength(EsdRecord, Length); + if (Length == 0) { + const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec); + if (PrEsdRecord) + EsdRecord = PrEsdRecord; + } + + uint32_t DefEsdId; + ESDRecord::getEsdId(EsdRecord, DefEsdId); + LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n'); + return DefEsdId; +} + +void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { + Sec.d.a++; + if ((Sec.d.a) >= SectionList.size()) + Sec.d.a = 0; +} + +Expected GOFFObjectFile::getSectionName(DataRefImpl Sec) const { + DataRefImpl EdSym; + SectionEntryImpl EsdIds = SectionList[Sec.d.a]; + EdSym.d.a = EsdIds.d.a; + Expected Name = getSymbolName(EdSym); + if (Name) { + StringRef Res = *Name; + LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n'); + LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n'); + Name = Res; + } + return Name; +} + +uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { + uint32_t Offset; + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + ESDRecord::getOffset(EsdRecord, Offset); + return Offset; +} + +uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const { + uint32_t Length; + uint32_t DefEsdId = getSectionDefEsdId(Sec); + const uint8_t *EsdRecord = EsdPtrs[DefEsdId]; + ESDRecord::getLength(EsdRecord, Length); + LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n'); + return static_cast(Length); +} + +// Unravel TXT records and expand fill characters to produce +// a contiguous sequence of bytes. +Expected> +GOFFObjectFile::getSectionContents(DataRefImpl Sec) const { + if (SectionDataCache.count(Sec.d.a)) { + auto &Buf = SectionDataCache[Sec.d.a]; + return ArrayRef(Buf); + } + uint64_t SectionSize = getSectionSize(Sec); + uint32_t DefEsdId = getSectionDefEsdId(Sec); + + const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec); + bool FillBytePresent; + ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent); + uint8_t FillByte = '\0'; + if (FillBytePresent) + ESDRecord::getFillByteValue(EdEsdRecord, FillByte); + + // Initialize section with fill byte. + SmallVector Data(SectionSize, FillByte); + + // Replace section with content from text records. + for (const uint8_t *TxtRecordInt : TextPtrs) { + const uint8_t *TxtRecordPtr = TxtRecordInt; + uint32_t TxtEsdId; + TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId); + LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n'); + + if (TxtEsdId != DefEsdId) + continue; + + uint32_t TxtDataOffset; + TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset); + + uint16_t TxtDataSize; + TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize); + + LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size " + << TxtDataSize << "\n"); + + SmallString<256> CompleteData; + CompleteData.reserve(TxtDataSize); + if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData)) + return std::move(Err); + assert(CompleteData.size() == TxtDataSize && "Wrong length of data"); + std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize, + Data.begin() + TxtDataOffset); + } + SectionDataCache[Sec.d.a] = Data; + return ArrayRef(Data); +} + +uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDAlignment Pow2Alignment; + ESDRecord::getAlignment(EsdRecord, Pow2Alignment); + return 1 << static_cast(Pow2Alignment); +} + +bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDExecutable Executable; + ESDRecord::getExecutable(EsdRecord, Executable); + return Executable == GOFF::ESD_EXE_CODE; +} + +bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDExecutable Executable; + ESDRecord::getExecutable(EsdRecord, Executable); + return Executable == GOFF::ESD_EXE_DATA; +} + +bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const { + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDLoadingBehavior LoadingBehavior; + ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); + return LoadingBehavior == GOFF::ESD_LB_NoLoad; +} + +bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const { + if (!isSectionData(Sec)) + return false; + + const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); + GOFF::ESDLoadingBehavior LoadingBehavior; + ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); + return LoadingBehavior == GOFF::ESD_LB_Initial; +} + +bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const { + // GOFF uses fill characters and fill characters are applied + // on getSectionContents() - so we say false to zero init. + return false; +} + section_iterator GOFFObjectFile::section_begin() const { DataRefImpl Sec; moveSectionNext(Sec); @@ -476,6 +636,13 @@ Error ESDRecord::getData(const uint8_t *Record, return getContinuousData(Record, DataSize, 72, CompleteData); } +Error TXTRecord::getData(const uint8_t *Record, + SmallString<256> &CompleteData) { + uint16_t Length; + getDataLength(Record, Length); + return getContinuousData(Record, Length, 24, CompleteData); +} + Error ENDRecord::getData(const uint8_t *Record, SmallString<256> &CompleteData) { uint16_t Length = getNameLength(Record); diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp index 734dac6b8507..69f60d016a80 100644 --- a/llvm/unittests/Object/GOFFObjectFileTest.cpp +++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp @@ -502,3 +502,100 @@ TEST(GOFFObjectFileTest, InvalidERSymbolType) { FailedWithMessage("ESD record 1 has unknown Executable type 0x03")); } } + +TEST(GOFFObjectFileTest, TXTConstruct) { + char GOFFData[GOFF::RecordLength * 6] = {}; + + // HDR record. + GOFFData[0] = 0x03; + GOFFData[1] = 0xF0; + GOFFData[50] = 0x01; + + // ESD record. + GOFFData[GOFF::RecordLength] = 0x03; + GOFFData[GOFF::RecordLength + 7] = 0x01; // ESDID. + GOFFData[GOFF::RecordLength + 71] = 0x05; // Size of symbol name. + GOFFData[GOFF::RecordLength + 72] = 0xa5; // Symbol name is v. + GOFFData[GOFF::RecordLength + 73] = 0x81; // Symbol name is a. + GOFFData[GOFF::RecordLength + 74] = 0x99; // Symbol name is r. + GOFFData[GOFF::RecordLength + 75] = 0x7b; // Symbol name is #. + GOFFData[GOFF::RecordLength + 76] = 0x83; // Symbol name is c. + + // ESD record. + GOFFData[GOFF::RecordLength * 2] = 0x03; + GOFFData[GOFF::RecordLength * 2 + 3] = 0x01; + GOFFData[GOFF::RecordLength * 2 + 7] = 0x02; // ESDID. + GOFFData[GOFF::RecordLength * 2 + 11] = 0x01; // Parent ESDID. + GOFFData[GOFF::RecordLength * 2 + 27] = 0x08; // Length. + GOFFData[GOFF::RecordLength * 2 + 40] = 0x01; // Name Space ID. + GOFFData[GOFF::RecordLength * 2 + 41] = 0x80; + GOFFData[GOFF::RecordLength * 2 + 60] = 0x04; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 61] = 0x04; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 63] = 0x0a; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 66] = 0x03; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 71] = 0x08; // Size of symbol name. + GOFFData[GOFF::RecordLength * 2 + 72] = 0xc3; // Symbol name is c. + GOFFData[GOFF::RecordLength * 2 + 73] = 0x6d; // Symbol name is _. + GOFFData[GOFF::RecordLength * 2 + 74] = 0xc3; // Symbol name is c. + GOFFData[GOFF::RecordLength * 2 + 75] = 0xd6; // Symbol name is o. + GOFFData[GOFF::RecordLength * 2 + 76] = 0xc4; // Symbol name is D. + GOFFData[GOFF::RecordLength * 2 + 77] = 0xc5; // Symbol name is E. + GOFFData[GOFF::RecordLength * 2 + 78] = 0xf6; // Symbol name is 6. + GOFFData[GOFF::RecordLength * 2 + 79] = 0xf4; // Symbol name is 4. + + // ESD record. + GOFFData[GOFF::RecordLength * 3] = 0x03; + GOFFData[GOFF::RecordLength * 3 + 3] = 0x02; + GOFFData[GOFF::RecordLength * 3 + 7] = 0x03; // ESDID. + GOFFData[GOFF::RecordLength * 3 + 11] = 0x02; // Parent ESDID. + GOFFData[GOFF::RecordLength * 3 + 71] = 0x05; // Size of symbol name. + GOFFData[GOFF::RecordLength * 3 + 72] = 0xa5; // Symbol name is v. + GOFFData[GOFF::RecordLength * 3 + 73] = 0x81; // Symbol name is a. + GOFFData[GOFF::RecordLength * 3 + 74] = 0x99; // Symbol name is r. + GOFFData[GOFF::RecordLength * 3 + 75] = 0x7b; // Symbol name is #. + GOFFData[GOFF::RecordLength * 3 + 76] = 0x83; // Symbol name is c. + + // TXT record. + GOFFData[GOFF::RecordLength * 4] = 0x03; + GOFFData[GOFF::RecordLength * 4 + 1] = 0x10; + GOFFData[GOFF::RecordLength * 4 + 7] = 0x02; + GOFFData[GOFF::RecordLength * 4 + 23] = 0x08; // Data Length. + GOFFData[GOFF::RecordLength * 4 + 24] = 0x12; + GOFFData[GOFF::RecordLength * 4 + 25] = 0x34; + GOFFData[GOFF::RecordLength * 4 + 26] = 0x56; + GOFFData[GOFF::RecordLength * 4 + 27] = 0x78; + GOFFData[GOFF::RecordLength * 4 + 28] = 0x9a; + GOFFData[GOFF::RecordLength * 4 + 29] = 0xbc; + GOFFData[GOFF::RecordLength * 4 + 30] = 0xde; + GOFFData[GOFF::RecordLength * 4 + 31] = 0xf0; + + // END record. + GOFFData[GOFF::RecordLength * 5] = 0x03; + GOFFData[GOFF::RecordLength * 5 + 1] = 0x40; + GOFFData[GOFF::RecordLength * 5 + 11] = 0x06; + + StringRef Data(GOFFData, GOFF::RecordLength * 6); + + Expected> GOFFObjOrErr = + object::ObjectFile::createGOFFObjectFile( + MemoryBufferRef(Data, "dummyGOFF")); + + ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded()); + + GOFFObjectFile *GOFFObj = dyn_cast((*GOFFObjOrErr).get()); + auto Symbols = GOFFObj->symbols(); + ASSERT_EQ(std::distance(Symbols.begin(), Symbols.end()), 1); + SymbolRef Symbol = *Symbols.begin(); + Expected SymbolNameOrErr = GOFFObj->getSymbolName(Symbol); + ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded()); + StringRef SymbolName = SymbolNameOrErr.get(); + EXPECT_EQ(SymbolName, "var#c"); + + auto Sections = GOFFObj->sections(); + ASSERT_EQ(std::distance(Sections.begin(), Sections.end()), 1); + SectionRef Section = *Sections.begin(); + Expected SectionContent = Section.getContents(); + ASSERT_THAT_EXPECTED(SectionContent, Succeeded()); + StringRef Contents = SectionContent.get(); + EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0"); +} -- GitLab From c388690a8b96cbdfa8c38a1e050088201da648e5 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Wed, 27 Mar 2024 16:54:50 +0100 Subject: [PATCH 073/541] [libc++][NFC] Simplify copy and move lowering to memmove a bit (#83574) We've introduced `__constexpr_memmove` a while ago, which simplified the implementation of the copy and move lowering a bit. This allows us to remove some of the boilerplate. --- libcxx/include/__algorithm/copy.h | 6 +-- libcxx/include/__algorithm/copy_backward.h | 6 +-- libcxx/include/__algorithm/copy_move_common.h | 39 ++++--------------- libcxx/include/__algorithm/move.h | 6 +-- libcxx/include/__algorithm/move_backward.h | 6 +-- 5 files changed, 15 insertions(+), 48 deletions(-) diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 4c3815405af0..0890b895f540 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -32,7 +32,7 @@ template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); template -struct __copy_loop { +struct __copy_impl { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -94,9 +94,7 @@ struct __copy_loop { __local_first = _Traits::__begin(++__segment_iterator); } } -}; -struct __copy_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -108,7 +106,7 @@ struct __copy_trivial { template pair<_InIter, _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __copy(_InIter __first, _Sent __last, _OutIter __result) { - return std::__dispatch_copy_or_move<_AlgPolicy, __copy_loop<_AlgPolicy>, __copy_trivial>( + return std::__copy_move_unwrap_iters<__copy_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h index 591dd21e2b03..73dc846a975a 100644 --- a/libcxx/include/__algorithm/copy_backward.h +++ b/libcxx/include/__algorithm/copy_backward.h @@ -33,7 +33,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter> __copy_backward(_InIter __first, _Sent __last, _OutIter __result); template -struct __copy_backward_loop { +struct __copy_backward_impl { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -104,9 +104,7 @@ struct __copy_backward_loop { __local_last = _Traits::__end(__segment_iterator); } } -}; -struct __copy_backward_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -118,7 +116,7 @@ struct __copy_backward_trivial { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> __copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { - return std::__dispatch_copy_or_move<_AlgPolicy, __copy_backward_loop<_AlgPolicy>, __copy_backward_trivial>( + return std::__copy_move_unwrap_iters<__copy_backward_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } diff --git a/libcxx/include/__algorithm/copy_move_common.h b/libcxx/include/__algorithm/copy_move_common.h index 845967b05038..12a26c6d6a64 100644 --- a/libcxx/include/__algorithm/copy_move_common.h +++ b/libcxx/include/__algorithm/copy_move_common.h @@ -81,30 +81,17 @@ __copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) { // Iterator unwrapping and dispatching to the correct overload. -template -struct __overload : _F1, _F2 { - using _F1::operator(); - using _F2::operator(); -}; - -template -struct __can_rewrap : false_type {}; - -template -struct __can_rewrap<_InIter, - _Sent, - _OutIter, - // Note that sentinels are always copy-constructible. - __enable_if_t< is_copy_constructible<_InIter>::value && is_copy_constructible<_OutIter>::value > > - : true_type {}; +template +struct __can_rewrap + : integral_constant::value && is_copy_constructible<_OutIter>::value> {}; template ::value, int> = 0> + __enable_if_t<__can_rewrap<_InIter, _OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> -__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { +__copy_move_unwrap_iters(_InIter __first, _Sent __last, _OutIter __out_first) { auto __range = std::__unwrap_range(__first, std::move(__last)); auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first)); return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)), @@ -115,24 +102,12 @@ template ::value, int> = 0> + __enable_if_t::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> -__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { +__copy_move_unwrap_iters(_InIter __first, _Sent __last, _OutIter __out_first) { return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first)); } -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> -__dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) { - using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>; - return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first)); -} - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h index bf574b527409..1716d43e2a61 100644 --- a/libcxx/include/__algorithm/move.h +++ b/libcxx/include/__algorithm/move.h @@ -34,7 +34,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIte __move(_InIter __first, _Sent __last, _OutIter __result); template -struct __move_loop { +struct __move_impl { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -95,9 +95,7 @@ struct __move_loop { __local_first = _Traits::__begin(++__segment_iterator); } } -}; -struct __move_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -109,7 +107,7 @@ struct __move_trivial { template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __move(_InIter __first, _Sent __last, _OutIter __result) { - return std::__dispatch_copy_or_move<_AlgPolicy, __move_loop<_AlgPolicy>, __move_trivial>( + return std::__copy_move_unwrap_iters<__move_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h index 6bb7c91d66c7..4beb7bdbaac0 100644 --- a/libcxx/include/__algorithm/move_backward.h +++ b/libcxx/include/__algorithm/move_backward.h @@ -33,7 +33,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1 __move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result); template -struct __move_backward_loop { +struct __move_backward_impl { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -104,9 +104,7 @@ struct __move_backward_loop { __local_last = _Traits::__end(--__segment_iterator); } } -}; -struct __move_backward_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -122,7 +120,7 @@ __move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _Bidirectiona std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); - return std::__dispatch_copy_or_move<_AlgPolicy, __move_backward_loop<_AlgPolicy>, __move_backward_trivial>( + return std::__copy_move_unwrap_iters<__move_backward_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } -- GitLab From 313bf28f98f714a0bd8f74a3beb4631d94428f89 Mon Sep 17 00:00:00 2001 From: David Green Date: Wed, 27 Mar 2024 16:04:48 +0000 Subject: [PATCH 074/541] [ARM][MVE] Remove kill flags when reusing VPR register. (#86300) The vpr register may no longer be killed where it was, so we should be removing the kill flags. --- .../ARM/MVETPAndVPTOptimisationsPass.cpp | 1 + .../CodeGen/Thumb2/mve-vpt-optimisations.mir | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp b/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp index 5c113ccfdc15..e8d2cba7ee55 100644 --- a/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp +++ b/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp @@ -958,6 +958,7 @@ bool MVETPAndVPTOptimisations::ReplaceConstByVPNOTs(MachineBasicBlock &MBB, unsigned NotImm = ~Imm & 0xffff; if (LastVPTReg != 0 && LastVPTReg != VPR && LastVPTImm == Imm) { + MRI->clearKillFlags(LastVPTReg); Instr.getOperand(PIdx + 1).setReg(LastVPTReg); if (MRI->use_empty(VPR)) { DeadInstructions.insert(Copy); diff --git a/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir b/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir index f28311e6563f..f9b175ed80fb 100644 --- a/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir +++ b/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+armv8.1-m.main,+hwdiv,+mve.fp,+ras,+thumb-mode -run-pass arm-mve-vpt-opts %s -o - | FileCheck %s +# RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+armv8.1-m.main,+hwdiv,+mve.fp,+ras,+thumb-mode -run-pass arm-mve-vpt-opts -verify-machineinstrs %s -o - | FileCheck %s --- name: vcmp_with_opposite_cond @@ -1021,3 +1021,26 @@ body: | %16:mqpr = MVE_VORR %15, %15, 1, %10, $noreg, undef %16 %17:mqpr = MVE_VORR %16, %16, 1, %11, $noreg, undef %17 ... +--- +name: reuse_kill_flags +alignment: 4 +body: | + bb.0: + ; CHECK-LABEL: name: reuse_kill_flags + ; CHECK: [[t2MOVi:%[0-9]+]]:tgpreven = t2MOVi 0, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: [[COPY:%[0-9]+]]:vccr = COPY [[t2MOVi]] + ; CHECK-NEXT: [[DEF:%[0-9]+]]:mqpr = IMPLICIT_DEF + ; CHECK-NEXT: [[MVE_VORR:%[0-9]+]]:mqpr = MVE_VORR [[DEF]], [[DEF]], 1, [[COPY]], $noreg, undef [[MVE_VORR]] + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:mqpr = IMPLICIT_DEF + ; CHECK-NEXT: [[MVE_VORR1:%[0-9]+]]:mqpr = MVE_VORR [[DEF1]], [[DEF1]], 1, killed [[COPY]], $noreg, undef [[MVE_VORR1]] + ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit [[DEF1]] + %0:tgpreven = t2MOVi 0, 14, $noreg, $noreg + %1:vccr = COPY %0:tgpreven + %2:mqpr = IMPLICIT_DEF + %3:mqpr = MVE_VORR %2:mqpr, %2:mqpr, 1, killed %1, $noreg, undef %3 + %4:vccr = COPY %0:tgpreven + %5:mqpr = IMPLICIT_DEF + %6:mqpr = MVE_VORR %5:mqpr, %5:mqpr, 1, killed %4, $noreg, undef %6 + tBX_RET 14 /* CC::al */, $noreg, implicit %5:mqpr + +... -- GitLab From 78f0871beed002187e65cc1334087596e9c11043 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 16:16:15 +0000 Subject: [PATCH 075/541] Revert rG58de1e2c5eee548a9b365e3b1554d87317072ad9 "Fix stack layout for frames larger than 2gb (#84114)" This is failing on some EXPENSIVE_CHECKS buildbots --- llvm/include/llvm/CodeGen/MachineFrameInfo.h | 14 +++---- .../llvm/CodeGen/TargetFrameLowering.h | 4 +- llvm/include/llvm/MC/MCAsmBackend.h | 2 +- llvm/include/llvm/MC/MCDwarf.h | 40 +++++++++---------- llvm/lib/CodeGen/CFIInstrInserter.cpp | 10 ++--- llvm/lib/CodeGen/MachineFrameInfo.cpp | 2 +- llvm/lib/CodeGen/PrologEpilogInserter.cpp | 4 +- llvm/lib/MC/MCDwarf.cpp | 6 +-- .../MCTargetDesc/AArch64AsmBackend.cpp | 10 ++--- llvm/lib/Target/ARM/ARMFrameLowering.cpp | 4 +- .../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 2 +- .../ARM/MCTargetDesc/ARMAsmBackendDarwin.h | 2 +- .../Target/Hexagon/HexagonFrameLowering.cpp | 4 +- .../lib/Target/MSP430/MSP430FrameLowering.cpp | 2 +- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 13 +++--- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 14 +++---- llvm/lib/Target/X86/X86FrameLowering.cpp | 28 ++++++------- llvm/lib/Target/X86/X86FrameLowering.h | 5 +-- llvm/lib/Target/X86/X86RegisterInfo.cpp | 10 ++--- llvm/test/CodeGen/PowerPC/huge-frame-size.ll | 2 +- llvm/test/CodeGen/X86/huge-stack.ll | 24 ----------- 21 files changed, 86 insertions(+), 116 deletions(-) delete mode 100644 llvm/test/CodeGen/X86/huge-stack.ll diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index ad6142b46515..0fe73fec7ee6 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -251,7 +251,7 @@ private: /// targets, this value is only used when generating debug info (via /// TargetRegisterInfo::getFrameIndexReference); when generating code, the /// corresponding adjustments are performed directly. - int64_t OffsetAdjustment = 0; + int OffsetAdjustment = 0; /// The prolog/epilog code inserter may process objects that require greater /// alignment than the default alignment the target provides. @@ -280,7 +280,7 @@ private: /// setup/destroy pseudo instructions (as defined in the TargetFrameInfo /// class). This information is important for frame pointer elimination. /// It is only valid during and after prolog/epilog code insertion. - uint64_t MaxCallFrameSize = ~UINT64_C(0); + unsigned MaxCallFrameSize = ~0u; /// The number of bytes of callee saved registers that the target wants to /// report for the current function in the CodeView S_FRAMEPROC record. @@ -591,10 +591,10 @@ public: uint64_t estimateStackSize(const MachineFunction &MF) const; /// Return the correction for frame offsets. - int64_t getOffsetAdjustment() const { return OffsetAdjustment; } + int getOffsetAdjustment() const { return OffsetAdjustment; } /// Set the correction for frame offsets. - void setOffsetAdjustment(int64_t Adj) { OffsetAdjustment = Adj; } + void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } /// Return the alignment in bytes that this function must be aligned to, /// which is greater than the default stack alignment provided by the target. @@ -655,7 +655,7 @@ public: /// CallFrameSetup/Destroy pseudo instructions are used by the target, and /// then only during or after prolog/epilog code insertion. /// - uint64_t getMaxCallFrameSize() const { + unsigned getMaxCallFrameSize() const { // TODO: Enable this assert when targets are fixed. //assert(isMaxCallFrameSizeComputed() && "MaxCallFrameSize not computed yet"); if (!isMaxCallFrameSizeComputed()) @@ -663,9 +663,9 @@ public: return MaxCallFrameSize; } bool isMaxCallFrameSizeComputed() const { - return MaxCallFrameSize != ~UINT64_C(0); + return MaxCallFrameSize != ~0u; } - void setMaxCallFrameSize(uint64_t S) { MaxCallFrameSize = S; } + void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } /// Returns how many bytes of callee-saved registers the target pushed in the /// prologue. Only used for debug info. diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 72978b2f746d..0b9cacecc7cb 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -51,7 +51,7 @@ public: // Maps a callee saved register to a stack slot with a fixed offset. struct SpillSlot { unsigned Reg; - int64_t Offset; // Offset relative to stack pointer on function entry. + int Offset; // Offset relative to stack pointer on function entry. }; struct DwarfFrameBase { @@ -66,7 +66,7 @@ public: // Used with FrameBaseKind::Register. unsigned Reg; // Used with FrameBaseKind::CFA. - int64_t Offset; + int Offset; struct WasmFrameBase WasmLoc; } Location; }; diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index 689e3cd5dbf2..01a64fb425a9 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -232,7 +232,7 @@ public: virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} /// Generate the compact unwind encoding for the CFI instructions. - virtual uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + virtual uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const { return 0; } diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h index 150b48eedc37..18056c5fdf81 100644 --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -508,7 +508,7 @@ private: MCSymbol *Label; unsigned Register; union { - int64_t Offset; + int Offset; unsigned Register2; }; unsigned AddressSpace = ~0u; @@ -516,7 +516,7 @@ private: std::vector Values; std::string Comment; - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, SMLoc Loc, + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, SMLoc Loc, StringRef V = "", StringRef Comment = "") : Operation(Op), Label(L), Register(R), Offset(O), Loc(Loc), Values(V.begin(), V.end()), Comment(Comment) { @@ -528,7 +528,7 @@ private: assert(Op == OpRegister); } - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, unsigned AS, + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS, SMLoc Loc) : Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS), Loc(Loc) { @@ -538,8 +538,8 @@ private: public: /// .cfi_def_cfa defines a rule for computing CFA as: take address from /// Register and add Offset to it. - static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, - int64_t Offset, SMLoc Loc = {}) { + static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset, + SMLoc Loc = {}) { return MCCFIInstruction(OpDefCfa, L, Register, Offset, Loc); } @@ -547,13 +547,13 @@ public: /// on Register will be used instead of the old one. Offset remains the same. static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpDefCfaRegister, L, Register, INT64_C(0), Loc); + return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, Loc); } /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register /// remains the same, but offset is new. Note that it is the absolute offset /// that will be added to a defined register to the compute CFA address. - static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, + static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset, SMLoc Loc = {}) { return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, Loc); } @@ -561,7 +561,7 @@ public: /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but /// Offset is a relative value that is added/subtracted from the previous /// offset. - static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int64_t Adjustment, + static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment, SMLoc Loc = {}) { return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, Loc); } @@ -581,7 +581,7 @@ public: /// .cfi_offset Previous value of Register is saved at offset Offset /// from CFA. static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, - int64_t Offset, SMLoc Loc = {}) { + int Offset, SMLoc Loc = {}) { return MCCFIInstruction(OpOffset, L, Register, Offset, Loc); } @@ -589,7 +589,7 @@ public: /// Offset from the current CFA register. This is transformed to .cfi_offset /// using the known displacement of the CFA register from the CFA. static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, - int64_t Offset, SMLoc Loc = {}) { + int Offset, SMLoc Loc = {}) { return MCCFIInstruction(OpRelOffset, L, Register, Offset, Loc); } @@ -602,12 +602,12 @@ public: /// .cfi_window_save SPARC register window is saved. static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpWindowSave, L, 0, INT64_C(0), Loc); + return MCCFIInstruction(OpWindowSave, L, 0, 0, Loc); } /// .cfi_negate_ra_state AArch64 negate RA state. static MCCFIInstruction createNegateRAState(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpNegateRAState, L, 0, INT64_C(0), Loc); + return MCCFIInstruction(OpNegateRAState, L, 0, 0, Loc); } /// .cfi_restore says that the rule for Register is now the same as it @@ -615,31 +615,31 @@ public: /// by .cfi_startproc were executed. static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpRestore, L, Register, INT64_C(0), Loc); + return MCCFIInstruction(OpRestore, L, Register, 0, Loc); } /// .cfi_undefined From now on the previous value of Register can't be /// restored anymore. static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpUndefined, L, Register, INT64_C(0), Loc); + return MCCFIInstruction(OpUndefined, L, Register, 0, Loc); } /// .cfi_same_value Current value of Register is the same as in the /// previous frame. I.e., no restoration is needed. static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register, SMLoc Loc = {}) { - return MCCFIInstruction(OpSameValue, L, Register, INT64_C(0), Loc); + return MCCFIInstruction(OpSameValue, L, Register, 0, Loc); } /// .cfi_remember_state Save all current rules for all registers. static MCCFIInstruction createRememberState(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpRememberState, L, 0, INT64_C(0), Loc); + return MCCFIInstruction(OpRememberState, L, 0, 0, Loc); } /// .cfi_restore_state Restore the previously saved state. static MCCFIInstruction createRestoreState(MCSymbol *L, SMLoc Loc = {}) { - return MCCFIInstruction(OpRestoreState, L, 0, INT64_C(0), Loc); + return MCCFIInstruction(OpRestoreState, L, 0, 0, Loc); } /// .cfi_escape Allows the user to add arbitrary bytes to the unwind @@ -650,7 +650,7 @@ public: } /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE - static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size, + static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size, SMLoc Loc = {}) { return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, Loc); } @@ -677,7 +677,7 @@ public: return AddressSpace; } - int64_t getOffset() const { + int getOffset() const { assert(Operation == OpDefCfa || Operation == OpOffset || Operation == OpRelOffset || Operation == OpDefCfaOffset || Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize || @@ -705,7 +705,7 @@ struct MCDwarfFrameInfo { unsigned CurrentCfaRegister = 0; unsigned PersonalityEncoding = 0; unsigned LsdaEncoding = 0; - uint64_t CompactUnwindEncoding = 0; + uint32_t CompactUnwindEncoding = 0; bool IsSignalFrame = false; bool IsSimple = false; unsigned RAReg = static_cast(INT_MAX); diff --git a/llvm/lib/CodeGen/CFIInstrInserter.cpp b/llvm/lib/CodeGen/CFIInstrInserter.cpp index 776cc13ccd20..87b062a16df1 100644 --- a/llvm/lib/CodeGen/CFIInstrInserter.cpp +++ b/llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -68,9 +68,9 @@ class CFIInstrInserter : public MachineFunctionPass { struct MBBCFAInfo { MachineBasicBlock *MBB; /// Value of cfa offset valid at basic block entry. - int64_t IncomingCFAOffset = -1; + int IncomingCFAOffset = -1; /// Value of cfa offset valid at basic block exit. - int64_t OutgoingCFAOffset = -1; + int OutgoingCFAOffset = -1; /// Value of cfa register valid at basic block entry. unsigned IncomingCFARegister = 0; /// Value of cfa register valid at basic block exit. @@ -120,7 +120,7 @@ class CFIInstrInserter : public MachineFunctionPass { /// Return the cfa offset value that should be set at the beginning of a MBB /// if needed. The negated value is needed when creating CFI instructions that /// set absolute offset. - int64_t getCorrectCFAOffset(MachineBasicBlock *MBB) { + int getCorrectCFAOffset(MachineBasicBlock *MBB) { return MBBVector[MBB->getNumber()].IncomingCFAOffset; } @@ -175,7 +175,7 @@ void CFIInstrInserter::calculateCFAInfo(MachineFunction &MF) { void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) { // Outgoing cfa offset set by the block. - int64_t SetOffset = MBBInfo.IncomingCFAOffset; + int SetOffset = MBBInfo.IncomingCFAOffset; // Outgoing cfa register set by the block. unsigned SetRegister = MBBInfo.IncomingCFARegister; MachineFunction *MF = MBBInfo.MBB->getParent(); @@ -188,7 +188,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) { for (MachineInstr &MI : *MBBInfo.MBB) { if (MI.isCFIInstruction()) { std::optional CSRReg; - std::optional CSROffset; + std::optional CSROffset; unsigned CFIIndex = MI.getOperand(0).getCFIIndex(); const MCCFIInstruction &CFI = Instrs[CFIIndex]; switch (CFI.getOperation()) { diff --git a/llvm/lib/CodeGen/MachineFrameInfo.cpp b/llvm/lib/CodeGen/MachineFrameInfo.cpp index e4b993850f73..853de4c88cae 100644 --- a/llvm/lib/CodeGen/MachineFrameInfo.cpp +++ b/llvm/lib/CodeGen/MachineFrameInfo.cpp @@ -197,7 +197,7 @@ void MachineFrameInfo::computeMaxCallFrameSize( for (MachineInstr &MI : MBB) { unsigned Opcode = MI.getOpcode(); if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) { - uint64_t Size = TII.getFrameSize(MI); + unsigned Size = TII.getFrameSize(MI); MaxCallFrameSize = std::max(MaxCallFrameSize, Size); if (FrameSDOps != nullptr) FrameSDOps->push_back(&MI); diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 9771825ed875..eaf96ec5cbde 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -366,8 +366,8 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) { return; // (Re-)Compute the MaxCallFrameSize. - [[maybe_unused]] uint64_t MaxCFSIn = - MFI.isMaxCallFrameSizeComputed() ? MFI.getMaxCallFrameSize() : UINT64_MAX; + [[maybe_unused]] uint32_t MaxCFSIn = + MFI.isMaxCallFrameSizeComputed() ? MFI.getMaxCallFrameSize() : UINT32_MAX; std::vector FrameSDOps; MFI.computeMaxCallFrameSize(MF, &FrameSDOps); assert(MFI.getMaxCallFrameSize() <= MaxCFSIn && diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index 9b8ec9bf2af0..2ee0c3eb27b9 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1298,8 +1298,8 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, namespace { class FrameEmitterImpl { - int64_t CFAOffset = 0; - int64_t InitialCFAOffset = 0; + int CFAOffset = 0; + int InitialCFAOffset = 0; bool IsEH; MCObjectStreamer &Streamer; @@ -1413,7 +1413,7 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) { if (!IsEH) Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg); - int64_t Offset = Instr.getOffset(); + int Offset = Instr.getOffset(); if (IsRelative) Offset -= CFAOffset; Offset = Offset / dataAlignmentFactor; diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index d83f7b5690ee..30ef3680ae79 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -584,7 +584,7 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend { /// Encode compact unwind stack adjustment for frameless functions. /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h. /// The stack size always needs to be 16 byte aligned. - uint64_t encodeStackAdjustment(uint64_t StackSize) const { + uint32_t encodeStackAdjustment(uint32_t StackSize) const { return (StackSize / 16) << 12; } @@ -602,7 +602,7 @@ public: } /// Generate the compact unwind encoding from the CFI directives. - uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override { ArrayRef Instrs = FI->Instructions; if (Instrs.empty()) @@ -612,10 +612,10 @@ public: return CU::UNWIND_ARM64_MODE_DWARF; bool HasFP = false; - uint64_t StackSize = 0; + unsigned StackSize = 0; - uint64_t CompactUnwindEncoding = 0; - int64_t CurOffset = 0; + uint32_t CompactUnwindEncoding = 0; + int CurOffset = 0; for (size_t i = 0, e = Instrs.size(); i != e; ++i) { const MCCFIInstruction &Inst = Instrs[i]; diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index a1012f3996e7..9b54dd4e4e61 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1165,7 +1165,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, if (STI.splitFramePushPop(MF)) { unsigned DwarfReg = MRI->getDwarfRegNum( Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true); - uint64_t Offset = MFI.getObjectOffset(FI); + unsigned Offset = MFI.getObjectOffset(FI); unsigned CFIIndex = MF.addFrameInst( MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) @@ -1187,7 +1187,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, if ((Reg >= ARM::D0 && Reg <= ARM::D31) && (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())) { unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); - uint64_t Offset = MFI.getObjectOffset(FI); + unsigned Offset = MFI.getObjectOffset(FI); unsigned CFIIndex = MF.addFrameInst( MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 9671f69bfd22..6cd4badb7704 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -1148,7 +1148,7 @@ enum CompactUnwindEncodings { /// instructions. If the CFI instructions describe a frame that cannot be /// encoded in compact unwind, the method returns UNWIND_ARM_MODE_DWARF which /// tells the runtime to fallback and unwind using dwarf. -uint64_t ARMAsmBackendDarwin::generateCompactUnwindEncoding( +uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding( const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const { DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n"); // Only armv7k uses CFI based unwinding. diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h index 9c958003ca75..ac0c9b101cae 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h @@ -34,7 +34,7 @@ public: /*Is64Bit=*/false, cantFail(MachO::getCPUType(TT)), Subtype); } - uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp index 394456c13e68..232651132d6e 100644 --- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -1660,7 +1660,7 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF, using SpillSlot = TargetFrameLowering::SpillSlot; unsigned NumFixed; - int64_t MinOffset = 0; // CS offsets are negative. + int MinOffset = 0; // CS offsets are negative. const SpillSlot *FixedSlots = getCalleeSavedSpillSlots(NumFixed); for (const SpillSlot *S = FixedSlots; S != FixedSlots+NumFixed; ++S) { if (!SRegs[S->Reg]) @@ -1679,7 +1679,7 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF, Register R = x; const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(R); unsigned Size = TRI->getSpillSize(*RC); - int64_t Off = MinOffset - Size; + int Off = MinOffset - Size; Align Alignment = std::min(TRI->getSpillAlign(*RC), getStackAlign()); Off &= -Alignment.value(); int FI = MFI.CreateFixedSpillStackObject(Size, Off); diff --git a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp index 6acbcf5cda24..176387d71fcb 100644 --- a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp +++ b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp @@ -294,7 +294,7 @@ void MSP430FrameLowering::emitEpilogue(MachineFunction &MF, if (!hasFP(MF)) { MBBI = FirstCSPop; - int64_t Offset = -(int64_t)CSSize - 2; + int64_t Offset = -CSSize - 2; // Mark callee-saved pop instruction. // Define the current CFA rule to use the provided offset. while (MBBI != MBB.end()) { diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 23bff777df6e..99dc9797f6df 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -1328,7 +1328,7 @@ public: /// Implementation of algorithm to generate the compact unwind encoding /// for the CFI instructions. - uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, + uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override { ArrayRef Instrs = FI->Instructions; if (Instrs.empty()) return 0; @@ -1343,13 +1343,13 @@ public: bool HasFP = false; // Encode that we are using EBP/RBP as the frame pointer. - uint64_t CompactUnwindEncoding = 0; + uint32_t CompactUnwindEncoding = 0; unsigned SubtractInstrIdx = Is64Bit ? 3 : 2; unsigned InstrOffset = 0; unsigned StackAdjust = 0; - uint64_t StackSize = 0; - int64_t MinAbsOffset = std::numeric_limits::max(); + unsigned StackSize = 0; + int MinAbsOffset = std::numeric_limits::max(); for (const MCCFIInstruction &Inst : Instrs) { switch (Inst.getOperation()) { @@ -1376,7 +1376,7 @@ public: memset(SavedRegs, 0, sizeof(SavedRegs)); StackAdjust = 0; SavedRegIdx = 0; - MinAbsOffset = std::numeric_limits::max(); + MinAbsOffset = std::numeric_limits::max(); InstrOffset += MoveInstrSize; break; } @@ -1419,8 +1419,7 @@ public: unsigned Reg = *MRI.getLLVMRegNum(Inst.getRegister(), true); SavedRegs[SavedRegIdx++] = Reg; StackAdjust += OffsetSize; - MinAbsOffset = - std::min(MinAbsOffset, std::abs(Inst.getOffset())); + MinAbsOffset = std::min(MinAbsOffset, abs(Inst.getOffset())); InstrOffset += PushInstrSize(Reg); break; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 1df2b86349a2..92a14226a0dc 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -358,8 +358,7 @@ private: void emitImmediate(const MCOperand &Disp, SMLoc Loc, unsigned ImmSize, MCFixupKind FixupKind, uint64_t StartByte, SmallVectorImpl &CB, - SmallVectorImpl &Fixups, - int64_t ImmOffset = 0) const; + SmallVectorImpl &Fixups, int ImmOffset = 0) const; void emitRegModRMByte(const MCOperand &ModRMReg, unsigned RegOpcodeFld, SmallVectorImpl &CB) const; @@ -413,8 +412,7 @@ static void emitConstant(uint64_t Val, unsigned Size, /// Determine if this immediate can fit in a disp8 or a compressed disp8 for /// EVEX instructions. \p will be set to the value to pass to the ImmOffset /// parameter of emitImmediate. -static bool isDispOrCDisp8(uint64_t TSFlags, int64_t Value, - int64_t &ImmOffset) { +static bool isDispOrCDisp8(uint64_t TSFlags, int Value, int &ImmOffset) { bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX; unsigned CD8_Scale = @@ -427,7 +425,7 @@ static bool isDispOrCDisp8(uint64_t TSFlags, int64_t Value, if (Value & (CD8_Scale - 1)) // Unaligned offset return false; - int64_t CDisp8 = Value / static_cast(CD8_Scale); + int CDisp8 = Value / static_cast(CD8_Scale); if (!isInt<8>(CDisp8)) return false; @@ -520,7 +518,7 @@ void X86MCCodeEmitter::emitImmediate(const MCOperand &DispOp, SMLoc Loc, uint64_t StartByte, SmallVectorImpl &CB, SmallVectorImpl &Fixups, - int64_t ImmOffset) const { + int ImmOffset) const { const MCExpr *Expr = nullptr; if (DispOp.isImm()) { // If this is a simple integer displacement that doesn't require a @@ -801,7 +799,7 @@ void X86MCCodeEmitter::emitMemModRMByte( // This also handles the 0 displacement for [EBP], [R13], [R21] or [R29]. We // can't use disp8 if the {disp32} pseudo prefix is present. if (Disp.isImm() && AllowDisp8) { - int64_t ImmOffset = 0; + int ImmOffset = 0; if (isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) { emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), CB); emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, CB, Fixups, @@ -828,7 +826,7 @@ void X86MCCodeEmitter::emitMemModRMByte( bool ForceDisp32 = false; bool ForceDisp8 = false; - int64_t ImmOffset = 0; + int ImmOffset = 0; if (BaseReg == 0) { // If there is no base register, we emit the special case SIB byte with // MOD=0, BASE=5, to JUST get the index, scale, and displacement. diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 3e44ed621fdf..d914e1b61ab0 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -380,9 +380,9 @@ MachineInstrBuilder X86FrameLowering::BuildStackAdjustment( return MI; } -int64_t X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - bool doMergeWithPrevious) const { +int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + bool doMergeWithPrevious) const { if ((doMergeWithPrevious && MBBI == MBB.begin()) || (!doMergeWithPrevious && MBBI == MBB.end())) return 0; @@ -405,7 +405,7 @@ int64_t X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, PI = std::prev(PI); unsigned Opc = PI->getOpcode(); - int64_t Offset = 0; + int Offset = 0; if ((Opc == X86::ADD64ri32 || Opc == X86::ADD32ri) && PI->getOperand(0).getReg() == StackPtr) { @@ -473,7 +473,7 @@ void X86FrameLowering::emitCalleeSavedFrameMovesFullCFA( : FramePtr; unsigned DwarfReg = MRI->getDwarfRegNum(MachineFramePtr, true); // Offset = space for return address + size of the frame pointer itself. - int64_t Offset = (Is64Bit ? 8 : 4) + (Uses64BitFramePtr ? 8 : 4); + unsigned Offset = (Is64Bit ? 8 : 4) + (Uses64BitFramePtr ? 8 : 4); BuildCFI(MBB, MBBI, DebugLoc{}, MCCFIInstruction::createOffset(nullptr, DwarfReg, -Offset)); emitCalleeSavedFrameMoves(MBB, MBBI, DebugLoc{}, true); @@ -1881,7 +1881,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // For EH funclets, only allocate enough space for outgoing calls. Save the // NumBytes value that we would've used for the parent frame. - uint64_t ParentFrameNumBytes = NumBytes; + unsigned ParentFrameNumBytes = NumBytes; if (IsFunclet) NumBytes = getWinEHFuncletFrameSize(MF); @@ -2430,7 +2430,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (HasFP) { if (X86FI->hasSwiftAsyncContext()) { // Discard the context. - int64_t Offset = 16 + mergeSPUpdates(MBB, MBBI, true); + int Offset = 16 + mergeSPUpdates(MBB, MBBI, true); emitSPUpdate(MBB, MBBI, DL, Offset, /*InEpilogue*/ true); } // Pop EBP. @@ -2562,7 +2562,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (!HasFP && NeedsDwarfCFI) { MBBI = FirstCSPop; - int64_t Offset = -(int64_t)CSSize - SlotSize; + int64_t Offset = -CSSize - SlotSize; // Mark callee-saved pop instruction. // Define the current CFA rule to use the provided offset. while (MBBI != MBB.end()) { @@ -2591,7 +2591,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, if (Terminator == MBB.end() || !isTailCallOpcode(Terminator->getOpcode())) { // Add the return addr area delta back since we are not tail calling. - int64_t Offset = -1 * X86FI->getTCReturnAddrDelta(); + int Offset = -1 * X86FI->getTCReturnAddrDelta(); assert(Offset >= 0 && "TCDelta should never be positive"); if (Offset) { // Check for possible merge with preceding ADD instruction. @@ -2625,7 +2625,7 @@ StackOffset X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, // object. // We need to factor in additional offsets applied during the prologue to the // frame, base, and stack pointer depending on which is used. - int64_t Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea(); + int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea(); const X86MachineFunctionInfo *X86FI = MF.getInfo(); unsigned CSSize = X86FI->getCalleeSavedFrameSize(); uint64_t StackSize = MFI.getStackSize(); @@ -3919,7 +3919,7 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( // FIXME: Don't set FrameSetup flag in catchret case. int FI = FuncInfo.EHRegNodeFrameIndex; - int64_t EHRegSize = MFI.getObjectSize(FI); + int EHRegSize = MFI.getObjectSize(FI); if (RestoreSP) { // MOV32rm -EHRegSize(%ebp), %esp @@ -3929,8 +3929,8 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( } Register UsedReg; - int64_t EHRegOffset = getFrameIndexReference(MF, FI, UsedReg).getFixed(); - int64_t EndOffset = -EHRegOffset - EHRegSize; + int EHRegOffset = getFrameIndexReference(MF, FI, UsedReg).getFixed(); + int EndOffset = -EHRegOffset - EHRegSize; FuncInfo.EHRegNodeEndOffset = EndOffset; if (UsedReg == FramePtr) { @@ -3951,7 +3951,7 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( .setMIFlag(MachineInstr::FrameSetup); // MOV32rm SavedEBPOffset(%esi), %ebp assert(X86FI->getHasSEHFramePtrSave()); - int64_t Offset = + int Offset = getFrameIndexReference(MF, X86FI->getSEHFramePtrSaveIndex(), UsedReg) .getFixed(); assert(UsedReg == BasePtr); diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h index 49580b31d39c..2dc9ecc6109d 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.h +++ b/llvm/lib/Target/X86/X86FrameLowering.h @@ -137,9 +137,8 @@ public: /// it is an ADD/SUB/LEA instruction it is deleted argument and the /// stack adjustment is returned as a positive value for ADD/LEA and /// a negative for SUB. - int64_t mergeSPUpdates(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - bool doMergeWithPrevious) const; + int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + bool doMergeWithPrevious) const; /// Emit a series of instructions to increment / decrement the stack /// pointer by a constant value. diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index 57f645462089..be0cf1596d0d 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -893,7 +893,7 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); // Determine base register and offset. - int64_t FIOffset; + int FIOffset; Register BasePtr; if (MI.isReturn()) { assert((!hasStackRealignment(MF) || @@ -946,11 +946,9 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, if (MI.getOperand(FIOperandNum+3).isImm()) { // Offset is a 32-bit integer. int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm()); - int64_t Offset = FIOffset + Imm; - if (!Is64Bit) { - assert(isInt<32>((long long)FIOffset + Imm) && - "Requesting 64-bit offset in 32-bit immediate!"); - } + int Offset = FIOffset + Imm; + assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) && + "Requesting 64-bit offset in 32-bit immediate!"); if (Offset != 0 || !tryOptimizeLEAtoMOV(II)) MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset); } else { diff --git a/llvm/test/CodeGen/PowerPC/huge-frame-size.ll b/llvm/test/CodeGen/PowerPC/huge-frame-size.ll index 78bdac021ac8..f1039df6f549 100644 --- a/llvm/test/CodeGen/PowerPC/huge-frame-size.ll +++ b/llvm/test/CodeGen/PowerPC/huge-frame-size.ll @@ -18,7 +18,7 @@ define void @foo(i8 %x) { ; CHECK-LE-NEXT: oris 0, 0, 65535 ; CHECK-LE-NEXT: ori 0, 0, 65504 ; CHECK-LE-NEXT: stdux 1, 1, 0 -; CHECK-LE-NEXT: .cfi_def_cfa_offset 4294967328 +; CHECK-LE-NEXT: .cfi_def_cfa_offset 32 ; CHECK-LE-NEXT: li 4, 1 ; CHECK-LE-NEXT: addi 5, 1, 32 ; CHECK-LE-NEXT: stb 3, 32(1) diff --git a/llvm/test/CodeGen/X86/huge-stack.ll b/llvm/test/CodeGen/X86/huge-stack.ll deleted file mode 100644 index 4596c50382a0..000000000000 --- a/llvm/test/CodeGen/X86/huge-stack.ll +++ /dev/null @@ -1,24 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --no_x86_scrub_sp --version 4 -; RUN: llc -O0 -mtriple=x86_64 < %s | FileCheck %s --check-prefix=CHECK -%large = type [4294967295 x i8] - -define void @foo() unnamed_addr #0 { -; CHECK-LABEL: foo: -; CHECK: # %bb.0: -; CHECK-NEXT: movabsq $8589934462, %rax # imm = 0x1FFFFFF7E -; CHECK-NEXT: subq %rax, %rsp -; CHECK-NEXT: .cfi_def_cfa_offset 8589934470 -; CHECK-NEXT: movb $42, 4294967167(%rsp) -; CHECK-NEXT: movb $43, -128(%rsp) -; CHECK-NEXT: movabsq $8589934462, %rax # imm = 0x1FFFFFF7E -; CHECK-NEXT: addq %rax, %rsp -; CHECK-NEXT: .cfi_def_cfa_offset 8 -; CHECK-NEXT: retq - %1 = alloca %large, align 1 - %2 = alloca %large, align 1 - %3 = getelementptr inbounds %large, ptr %1, i64 0, i64 0 - store i8 42, ptr %3, align 1 - %4 = getelementptr inbounds %large, ptr %2, i64 0, i64 0 - store i8 43, ptr %4, align 1 - ret void -} -- GitLab From 77118536b52bf5256eed85f61451d0beb6cf5dc3 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Wed, 27 Mar 2024 17:22:41 +0100 Subject: [PATCH 076/541] [libc] Remove obsolete LIBC_HAS_BUILTIN macro (#86554) Fixes #86546 and removes the macro `LIBC_HAS_BUILTIN`. This was necessary to support older compilers that did not support `__has_builtin`. All of the compilers we support already have this builtin. See: https://libc.llvm.org/compiler_support.html All uses now use `__has_builtin` directly cc @nickdesaulniers --- libc/docs/dev/code_style.rst | 2 +- libc/src/__support/CPP/CMakeLists.txt | 2 - libc/src/__support/CPP/atomic.h | 74 ++++++++++--------- libc/src/__support/CPP/bit.h | 15 ++-- .../__support/CPP/type_traits/add_pointer.h | 1 - libc/src/__support/CPP/type_traits/decay.h | 1 - .../CPP/type_traits/is_destructible.h | 3 +- .../__support/CPP/type_traits/is_function.h | 3 +- .../CPP/type_traits/is_lvalue_reference.h | 3 +- .../__support/CPP/type_traits/is_reference.h | 3 +- .../CPP/type_traits/is_rvalue_reference.h | 3 +- .../CPP/type_traits/is_trivially_copyable.h | 1 - .../type_traits/is_trivially_destructible.h | 5 +- .../CPP/type_traits/remove_all_extents.h | 3 +- libc/src/__support/FPUtil/CMakeLists.txt | 1 - libc/src/__support/FPUtil/FEnvImpl.h | 1 - libc/src/__support/FPUtil/gpu/FMA.h | 8 +- libc/src/__support/macros/config.h | 18 ----- libc/src/__support/macros/optimization.h | 1 - libc/src/__support/macros/sanitizer.h | 3 +- libc/src/__support/math_extras.h | 9 +-- libc/src/__support/memory_size.h | 2 +- .../src/string/memory_utils/generic/builtin.h | 8 +- libc/src/string/memory_utils/utils.h | 5 +- libc/utils/gpu/server/rpc_server.cpp | 5 ++ .../llvm-project-overlay/libc/BUILD.bazel | 4 - 26 files changed, 77 insertions(+), 107 deletions(-) diff --git a/libc/docs/dev/code_style.rst b/libc/docs/dev/code_style.rst index e6fc6df5a0f6..22a18b7a4cc1 100644 --- a/libc/docs/dev/code_style.rst +++ b/libc/docs/dev/code_style.rst @@ -55,7 +55,7 @@ We define two kinds of macros: * ``src/__support/macros/config.h`` - Important compiler and platform features. Such macros can be used to produce portable code by parameterizing compilation based on the presence or lack of a given - feature. e.g., ``LIBC_HAS_BUILTIN`` + feature. e.g., ``LIBC_HAS_FEATURE`` * ``src/__support/macros/attributes.h`` - Attributes for functions, types, and variables. e.g., ``LIBC_UNUSED`` * ``src/__support/macros/optimization.h`` - Portable macros for performance diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt index f76285be5219..84d01fe04516 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -18,7 +18,6 @@ add_header_library( .limits .type_traits libc.src.__support.macros.attributes - libc.src.__support.macros.config libc.src.__support.macros.sanitizer ) @@ -157,7 +156,6 @@ add_header_library( DEPENDS libc.include.llvm-libc-macros.stdfix_macros libc.src.__support.macros.attributes - libc.src.__support.macros.config libc.src.__support.macros.properties.types ) diff --git a/libc/src/__support/CPP/atomic.h b/libc/src/__support/CPP/atomic.h index b74cb5981dba..5e428940565b 100644 --- a/libc/src/__support/CPP/atomic.h +++ b/libc/src/__support/CPP/atomic.h @@ -71,10 +71,11 @@ public: T load(MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_load_n)) - return __scoped_atomic_load_n(&val, int(mem_ord), (int)(mem_scope)); - else - return __atomic_load_n(&val, int(mem_ord)); +#if __has_builtin(__scoped_atomic_load_n) + return __scoped_atomic_load_n(&val, int(mem_ord), (int)(mem_scope)); +#else + return __atomic_load_n(&val, int(mem_ord)); +#endif } // Atomic store. @@ -85,10 +86,11 @@ public: void store(T rhs, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_store_n)) - __scoped_atomic_store_n(&val, rhs, int(mem_ord), (int)(mem_scope)); - else - __atomic_store_n(&val, rhs, int(mem_ord)); +#if __has_builtin(__scoped_atomic_store_n) + __scoped_atomic_store_n(&val, rhs, int(mem_ord), (int)(mem_scope)); +#else + __atomic_store_n(&val, rhs, int(mem_ord)); +#endif } // Atomic compare exchange @@ -101,47 +103,51 @@ public: T exchange(T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_exchange_n)) - return __scoped_atomic_exchange_n(&val, desired, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_exchange_n(&val, desired, int(mem_ord)); +#if __has_builtin(__scoped_atomic_exchange_n) + return __scoped_atomic_exchange_n(&val, desired, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_exchange_n(&val, desired, int(mem_ord)); +#endif } T fetch_add(T increment, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_add)) - return __scoped_atomic_fetch_add(&val, increment, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_add(&val, increment, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_add) + return __scoped_atomic_fetch_add(&val, increment, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_fetch_add(&val, increment, int(mem_ord)); +#endif } T fetch_or(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_or)) - return __scoped_atomic_fetch_or(&val, mask, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_or(&val, mask, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_or) + return __scoped_atomic_fetch_or(&val, mask, int(mem_ord), (int)(mem_scope)); +#else + return __atomic_fetch_or(&val, mask, int(mem_ord)); +#endif } T fetch_and(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_and)) - return __scoped_atomic_fetch_and(&val, mask, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_and(&val, mask, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_and) + return __scoped_atomic_fetch_and(&val, mask, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_fetch_and(&val, mask, int(mem_ord)); +#endif } T fetch_sub(T decrement, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_sub)) - return __scoped_atomic_fetch_sub(&val, decrement, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_sub(&val, decrement, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_sub) + return __scoped_atomic_fetch_sub(&val, decrement, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_fetch_sub(&val, decrement, int(mem_ord)); +#endif } // Set the value without using an atomic operation. This is useful @@ -166,7 +172,7 @@ LIBC_INLINE void atomic_thread_fence([[maybe_unused]] MemoryOrder mem_ord) { // except no instructions for memory ordering are issued. Only reordering of // the instructions by the compiler is suppressed as order instructs. LIBC_INLINE void atomic_signal_fence([[maybe_unused]] MemoryOrder mem_ord) { -#if LIBC_HAS_BUILTIN(__atomic_signal_fence) +#if __has_builtin(__atomic_signal_fence) __atomic_signal_fence(static_cast(mem_ord)); #else // if the builtin is not ready, use asm as a full compiler barrier. diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index 526c499adc37..80f50fd221ef 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -14,14 +14,13 @@ #include "src/__support/CPP/limits.h" // numeric_limits #include "src/__support/CPP/type_traits.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/sanitizer.h" #include namespace LIBC_NAMESPACE::cpp { -#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#if __has_builtin(__builtin_memcpy_inline) #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE #endif @@ -36,20 +35,20 @@ LIBC_INLINE constexpr cpp::enable_if_t< To> bit_cast(const From &from) { MSAN_UNPOISON(&from, sizeof(From)); -#if LIBC_HAS_BUILTIN(__builtin_bit_cast) +#if __has_builtin(__builtin_bit_cast) return __builtin_bit_cast(To, from); #else To to; char *dst = reinterpret_cast(&to); const char *src = reinterpret_cast(&from); -#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#if __has_builtin(__builtin_memcpy_inline) __builtin_memcpy_inline(dst, src, sizeof(To)); #else for (unsigned i = 0; i < sizeof(To); ++i) dst[i] = src[i]; -#endif // LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#endif // __has_builtin(__builtin_memcpy_inline) return to; -#endif // LIBC_HAS_BUILTIN(__builtin_bit_cast) +#endif // __has_builtin(__builtin_bit_cast) } template @@ -94,7 +93,7 @@ countr_zero(T value) { } return zero_bits; } -#if LIBC_HAS_BUILTIN(__builtin_ctzs) +#if __has_builtin(__builtin_ctzs) ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs) #endif ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz) @@ -124,7 +123,7 @@ countl_zero(T value) { } return zero_bits; } -#if LIBC_HAS_BUILTIN(__builtin_clzs) +#if __has_builtin(__builtin_clzs) ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs) #endif ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz) diff --git a/libc/src/__support/CPP/type_traits/add_pointer.h b/libc/src/__support/CPP/type_traits/add_pointer.h index 72a764bb8ba6..1257033ee80e 100644 --- a/libc/src/__support/CPP/type_traits/add_pointer.h +++ b/libc/src/__support/CPP/type_traits/add_pointer.h @@ -10,7 +10,6 @@ #include "src/__support/CPP/type_traits/remove_reference.h" #include "src/__support/CPP/type_traits/type_identity.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { diff --git a/libc/src/__support/CPP/type_traits/decay.h b/libc/src/__support/CPP/type_traits/decay.h index a018286fddd8..f1a1200ab2ba 100644 --- a/libc/src/__support/CPP/type_traits/decay.h +++ b/libc/src/__support/CPP/type_traits/decay.h @@ -9,7 +9,6 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_DECAY_H #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" #include "src/__support/CPP/type_traits/add_pointer.h" #include "src/__support/CPP/type_traits/conditional.h" diff --git a/libc/src/__support/CPP/type_traits/is_destructible.h b/libc/src/__support/CPP/type_traits/is_destructible.h index d47de1cc797b..f94fe309ac8f 100644 --- a/libc/src/__support/CPP/type_traits/is_destructible.h +++ b/libc/src/__support/CPP/type_traits/is_destructible.h @@ -16,12 +16,11 @@ #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/CPP/type_traits/type_identity.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_destructible -#if LIBC_HAS_BUILTIN(__is_destructible) +#if __has_builtin(__is_destructible) template struct is_destructible : bool_constant<__is_destructible(T)> {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_function.h b/libc/src/__support/CPP/type_traits/is_function.h index 557b3224484b..0eba5860ad60 100644 --- a/libc/src/__support/CPP/type_traits/is_function.h +++ b/libc/src/__support/CPP/type_traits/is_function.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/is_const.h" #include "src/__support/CPP/type_traits/is_reference.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_function -#if LIBC_HAS_BUILTIN(__is_function) +#if __has_builtin(__is_function) template struct is_function : integral_constant {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_lvalue_reference.h b/libc/src/__support/CPP/type_traits/is_lvalue_reference.h index f52e303afad2..1dff57f186a3 100644 --- a/libc/src/__support/CPP/type_traits/is_lvalue_reference.h +++ b/libc/src/__support/CPP/type_traits/is_lvalue_reference.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_lvalue_reference -#if LIBC_HAS_BUILTIN(__is_lvalue_reference) +#if __has_builtin(__is_lvalue_reference) template struct is_lvalue_reference : bool_constant<__is_lvalue_reference(T)> {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_reference.h b/libc/src/__support/CPP/type_traits/is_reference.h index c017028edf41..bbfb2b7359c3 100644 --- a/libc/src/__support/CPP/type_traits/is_reference.h +++ b/libc/src/__support/CPP/type_traits/is_reference.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_reference -#if LIBC_HAS_BUILTIN(__is_reference) +#if __has_builtin(__is_reference) template struct is_reference : bool_constant<__is_reference(T)> {}; #else template struct is_reference : public false_type {}; diff --git a/libc/src/__support/CPP/type_traits/is_rvalue_reference.h b/libc/src/__support/CPP/type_traits/is_rvalue_reference.h index f0487e41c998..3efbbe6b033a 100644 --- a/libc/src/__support/CPP/type_traits/is_rvalue_reference.h +++ b/libc/src/__support/CPP/type_traits/is_rvalue_reference.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_rvalue_reference -#if LIBC_HAS_BUILTIN(__is_rvalue_reference) +#if __has_builtin(__is_rvalue_reference) template struct is_rvalue_reference : bool_constant<__is_rvalue_reference(T)> {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_trivially_copyable.h b/libc/src/__support/CPP/type_traits/is_trivially_copyable.h index 0c3fdcc711d5..b4c825d57961 100644 --- a/libc/src/__support/CPP/type_traits/is_trivially_copyable.h +++ b/libc/src/__support/CPP/type_traits/is_trivially_copyable.h @@ -9,7 +9,6 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_H #include "src/__support/CPP/type_traits/integral_constant.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { diff --git a/libc/src/__support/CPP/type_traits/is_trivially_destructible.h b/libc/src/__support/CPP/type_traits/is_trivially_destructible.h index 3345149433af..37e0e869266e 100644 --- a/libc/src/__support/CPP/type_traits/is_trivially_destructible.h +++ b/libc/src/__support/CPP/type_traits/is_trivially_destructible.h @@ -11,12 +11,11 @@ #include "src/__support/CPP/type_traits/bool_constant.h" #include "src/__support/CPP/type_traits/is_destructible.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_trivially_destructible -#if LIBC_HAS_BUILTIN(__is_trivially_destructible) +#if __has_builtin(__is_trivially_destructible) template struct is_trivially_destructible : public bool_constant<__is_trivially_destructible(T)> {}; @@ -25,7 +24,7 @@ template struct is_trivially_destructible : public bool_constant &&__has_trivial_destructor( T)> {}; -#endif // LIBC_HAS_BUILTIN(__is_trivially_destructible) +#endif // __has_builtin(__is_trivially_destructible) template LIBC_INLINE_VAR constexpr bool is_trivially_destructible_v = is_trivially_destructible::value; diff --git a/libc/src/__support/CPP/type_traits/remove_all_extents.h b/libc/src/__support/CPP/type_traits/remove_all_extents.h index bff6341d3e45..5941b82bbc16 100644 --- a/libc/src/__support/CPP/type_traits/remove_all_extents.h +++ b/libc/src/__support/CPP/type_traits/remove_all_extents.h @@ -9,14 +9,13 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_ALL_EXTENTS_H #include "src/__support/CPP/type_traits/type_identity.h" -#include "src/__support/macros/config.h" #include // size_t namespace LIBC_NAMESPACE::cpp { // remove_all_extents -#if LIBC_HAS_BUILTIN(__remove_all_extents) +#if __has_builtin(__remove_all_extents) template using remove_all_extents_t = __remove_all_extents(T); template struct remove_all_extents : cpp::type_identity> {}; diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index 0f4350234197..ff155a19758d 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -6,7 +6,6 @@ add_header_library( libc.include.fenv libc.include.math libc.src.__support.macros.attributes - libc.src.__support.macros.config libc.src.errno.errno ) diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h index a6a533dcfdf4..6086d5d3de2d 100644 --- a/libc/src/__support/FPUtil/FEnvImpl.h +++ b/libc/src/__support/FPUtil/FEnvImpl.h @@ -11,7 +11,6 @@ #include "include/llvm-libc-macros/math-macros.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/properties/architectures.h" #include "src/errno/libc_errno.h" #include diff --git a/libc/src/__support/FPUtil/gpu/FMA.h b/libc/src/__support/FPUtil/gpu/FMA.h index 86bc86031496..ef1cd26a72dd 100644 --- a/libc/src/__support/FPUtil/gpu/FMA.h +++ b/libc/src/__support/FPUtil/gpu/FMA.h @@ -10,12 +10,12 @@ #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GPU_FMA_H #include "src/__support/CPP/type_traits.h" -#include "src/__support/macros/config.h" -// These intrinsics map to the FMA instrunctions in the target ISA for the GPU. +// These intrinsics map to the FMA instructions in the target ISA for the GPU. // The default rounding mode generated from these will be to the nearest even. -static_assert(LIBC_HAS_BUILTIN(__builtin_fma), "FMA builtins must be defined"); -static_assert(LIBC_HAS_BUILTIN(__builtin_fmaf), "FMA builtins must be defined"); +#if !__has_builtin(__builtin_fma) || !__has_builtin(__builtin_fmaf) +#error "FMA builtins must be defined"); +#endif namespace LIBC_NAMESPACE { namespace fputil { diff --git a/libc/src/__support/macros/config.h b/libc/src/__support/macros/config.h index 6666c1366696..3f200f0d62ba 100644 --- a/libc/src/__support/macros/config.h +++ b/libc/src/__support/macros/config.h @@ -13,24 +13,6 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H #define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H -// LIBC_HAS_BUILTIN() -// -// Checks whether the compiler supports a Clang Feature Checking Macro, and if -// so, checks whether it supports the provided builtin function "x" where x -// is one of the functions noted in -// https://clang.llvm.org/docs/LanguageExtensions.html -// -// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. -// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html - -// Compiler builtin-detection. -// clang.llvm.org/docs/LanguageExtensions.html#has-builtin -#ifdef __has_builtin -#define LIBC_HAS_BUILTIN(x) __has_builtin(x) -#else -#define LIBC_HAS_BUILTIN(x) 0 -#endif - // Compiler feature-detection. // clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension #ifdef __has_feature diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h index ae97efcaa417..59886ca44be1 100644 --- a/libc/src/__support/macros/optimization.h +++ b/libc/src/__support/macros/optimization.h @@ -11,7 +11,6 @@ #define LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG // We use a template to implement likely/unlikely to make sure that we don't diff --git a/libc/src/__support/macros/sanitizer.h b/libc/src/__support/macros/sanitizer.h index fc66c2005c42..bd9b62b7121a 100644 --- a/libc/src/__support/macros/sanitizer.h +++ b/libc/src/__support/macros/sanitizer.h @@ -47,8 +47,7 @@ // Functions to unpoison memory //----------------------------------------------------------------------------- -#if defined(LIBC_HAVE_MEMORY_SANITIZER) && \ - LIBC_HAS_BUILTIN(__builtin_constant_p) +#if defined(LIBC_HAVE_MEMORY_SANITIZER) && __has_builtin(__builtin_constant_p) // Only perform MSAN unpoison in non-constexpr context. #include #define MSAN_UNPOISON(addr, size) \ diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h index 28ee1be8b999..70a8800b285d 100644 --- a/libc/src/__support/math_extras.h +++ b/libc/src/__support/math_extras.h @@ -14,7 +14,6 @@ #include "src/__support/CPP/limits.h" // CHAR_BIT, numeric_limits #include "src/__support/CPP/type_traits.h" // is_unsigned_v #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN namespace LIBC_NAMESPACE { @@ -61,7 +60,7 @@ add_with_carry(T a, T b, T carry_in) { return add_with_carry_const(a, b, carry_in); } -#if LIBC_HAS_BUILTIN(__builtin_addc) +#if __has_builtin(__builtin_addc) // https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins template <> @@ -129,7 +128,7 @@ add_with_carry(unsigned long long a, unsigned long long b, } } -#endif // LIBC_HAS_BUILTIN(__builtin_addc) +#endif // __has_builtin(__builtin_addc) // Subtract with borrow template struct DiffBorrow { @@ -157,7 +156,7 @@ sub_with_borrow(T a, T b, T borrow_in) { return sub_with_borrow_const(a, b, borrow_in); } -#if LIBC_HAS_BUILTIN(__builtin_subc) +#if __has_builtin(__builtin_subc) // https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins template <> @@ -225,7 +224,7 @@ sub_with_borrow(unsigned long long a, unsigned long long b, } } -#endif // LIBC_HAS_BUILTIN(__builtin_subc) +#endif // __has_builtin(__builtin_subc) template [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> diff --git a/libc/src/__support/memory_size.h b/libc/src/__support/memory_size.h index 7bd16a1695be..491123bbabf3 100644 --- a/libc/src/__support/memory_size.h +++ b/libc/src/__support/memory_size.h @@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE { namespace internal { template LIBC_INLINE bool mul_overflow(T a, T b, T *res) { -#if LIBC_HAS_BUILTIN(__builtin_mul_overflow) +#if __has_builtin(__builtin_mul_overflow) return __builtin_mul_overflow(a, b, res); #else T max = cpp::numeric_limits::max(); diff --git a/libc/src/string/memory_utils/generic/builtin.h b/libc/src/string/memory_utils/generic/builtin.h index 5239329f653b..ba4f4b898408 100644 --- a/libc/src/string/memory_utils/generic/builtin.h +++ b/libc/src/string/memory_utils/generic/builtin.h @@ -10,16 +10,16 @@ #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_BUILTIN_H #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/string/memory_utils/utils.h" // Ptr, CPtr #include // size_t namespace LIBC_NAMESPACE { -static_assert(LIBC_HAS_BUILTIN(__builtin_memcpy), "Builtin not defined"); -static_assert(LIBC_HAS_BUILTIN(__builtin_memset), "Builtin not defined"); -static_assert(LIBC_HAS_BUILTIN(__builtin_memmove), "Builtin not defined"); +#if !__has_builtin(__builtin_memcpy) || !__has_builtin(__builtin_memset) || \ + !__has_builtin(__builtin_memmove) +#error "Builtin not defined"); +#endif [[maybe_unused]] LIBC_INLINE void inline_memcpy_builtin(Ptr dst, CPtr src, size_t count, size_t offset = 0) { diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h index 79526d19c6b3..b3e1a26ad996 100644 --- a/libc/src/string/memory_utils/utils.h +++ b/libc/src/string/memory_utils/utils.h @@ -14,7 +14,6 @@ #include "src/__support/CPP/type_traits.h" #include "src/__support/endian.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/properties/architectures.h" #include // size_t @@ -71,11 +70,11 @@ LIBC_INLINE bool is_disjoint(const void *p1, const void *p2, size_t size) { return sdiff >= 0 ? size <= udiff : size <= neg_udiff; } -#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#if __has_builtin(__builtin_memcpy_inline) #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE #endif -#if LIBC_HAS_BUILTIN(__builtin_memset_inline) +#if __has_builtin(__builtin_memset_inline) #define LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE #endif diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 90af1569c4c5..46ad98fa02cc 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// Workaround for missing __has_builtin in < GCC 10. +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + #include "llvmlibc_rpc_server.h" #include "src/__support/RPC/rpc.h" diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index e0790e0ab59e..eb0afbb6dd6f 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -216,7 +216,6 @@ libc_support_library( ":__support_cpp_limits", ":__support_cpp_type_traits", ":__support_macros_attributes", - ":__support_macros_config", ":__support_macros_sanitizer", ], ) @@ -383,7 +382,6 @@ libc_support_library( ], deps = [ ":__support_macros_attributes", - ":__support_macros_config", ":__support_macros_properties_types", ":llvm_libc_macros_stdfix_macros", ], @@ -663,7 +661,6 @@ libc_support_library( ":__support_cpp_limits", ":__support_cpp_type_traits", ":__support_macros_attributes", - ":__support_macros_config", ], ) @@ -2318,7 +2315,6 @@ libc_support_library( ":__support_cpp_cstddef", ":__support_cpp_type_traits", ":__support_macros_attributes", - ":__support_macros_config", ":__support_macros_optimization", ":__support_macros_properties_architectures", ":__support_macros_properties_cpu_features", -- GitLab From 6a0ec8e25cba9d398cf525889c53835cf40247a3 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Wed, 27 Mar 2024 09:25:46 -0700 Subject: [PATCH 077/541] [lldb] Revive shell test after updating UnwindTable (#86770) In commit 2f63718f8567413a1c596bda803663eb58d6da5a Author: Jason Molenda Date: Tue Mar 26 09:07:15 2024 -0700 [lldb] Don't clear a Module's UnwindTable when adding a SymbolFile (#86603) I stopped clearing a Module's UnwindTable when we add a SymbolFile to avoid the memory management problems with adding a symbol file asynchronously while the UnwindTable is being accessed on another thread. This broke the target-symbols-add-unwind.test shell test on Linux which removes the DWARF debub_frame section from a binary, loads it, then loads the unstripped binary with the DWARF debug_frame section and checks that the UnwindPlans for a function include debug_frame. I originally decided that I was willing to sacrifice the possiblity of additional unwind sources from a symbol file because we rely on assembly emulation so heavily, they're rarely critical. But there are targets where we we don't have emluation and rely on things like DWARF debug_frame a lot more, so this probably wasn't a good choice. This patch adds a new UnwindTable::Update method which looks for any new sources of unwind information and adds it to the UnwindTable, and calls that after a new SymbolFile has been added to a Module. --- lldb/include/lldb/Symbol/UnwindTable.h | 4 ++ lldb/source/Core/Module.cpp | 2 + lldb/source/Symbol/UnwindTable.cpp | 45 +++++++++++++++++++ .../SymbolFile/target-symbols-add-unwind.test | 27 +++++++++++ 4 files changed, 78 insertions(+) create mode 100644 lldb/test/Shell/SymbolFile/target-symbols-add-unwind.test diff --git a/lldb/include/lldb/Symbol/UnwindTable.h b/lldb/include/lldb/Symbol/UnwindTable.h index f0ce7047de2d..26826e5d1b49 100644 --- a/lldb/include/lldb/Symbol/UnwindTable.h +++ b/lldb/include/lldb/Symbol/UnwindTable.h @@ -57,6 +57,10 @@ public: ArchSpec GetArchitecture(); + /// Called after a SymbolFile has been added to a Module to add any new + /// unwind sections that may now be available. + void Update(); + private: void Dump(Stream &s); diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index a520523a9652..9c105b3f0e57 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1009,6 +1009,8 @@ SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) { m_symfile_up.reset( SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); m_did_load_symfile = true; + if (m_unwind_table) + m_unwind_table->Update(); } } } diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp index 3c1a5187b110..11bedf3d6052 100644 --- a/lldb/source/Symbol/UnwindTable.cpp +++ b/lldb/source/Symbol/UnwindTable.cpp @@ -84,6 +84,51 @@ void UnwindTable::Initialize() { } } +void UnwindTable::Update() { + if (!m_initialized) + return Initialize(); + + std::lock_guard guard(m_mutex); + + ObjectFile *object_file = m_module.GetObjectFile(); + if (!object_file) + return; + + if (!m_object_file_unwind_up) + m_object_file_unwind_up = object_file->CreateCallFrameInfo(); + + SectionList *sl = m_module.GetSectionList(); + if (!sl) + return; + + SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true); + if (!m_eh_frame_up && sect) { + m_eh_frame_up = std::make_unique( + *object_file, sect, DWARFCallFrameInfo::EH); + } + + sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true); + if (!m_debug_frame_up && sect) { + m_debug_frame_up = std::make_unique( + *object_file, sect, DWARFCallFrameInfo::DWARF); + } + + sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true); + if (!m_compact_unwind_up && sect) { + m_compact_unwind_up = + std::make_unique(*object_file, sect); + } + + sect = sl->FindSectionByType(eSectionTypeARMexidx, true); + if (!m_arm_unwind_up && sect) { + SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true); + if (sect_extab.get()) { + m_arm_unwind_up = + std::make_unique(*object_file, sect, sect_extab); + } + } +} + UnwindTable::~UnwindTable() = default; std::optional diff --git a/lldb/test/Shell/SymbolFile/target-symbols-add-unwind.test b/lldb/test/Shell/SymbolFile/target-symbols-add-unwind.test new file mode 100644 index 000000000000..5420213d405e --- /dev/null +++ b/lldb/test/Shell/SymbolFile/target-symbols-add-unwind.test @@ -0,0 +1,27 @@ +# TODO: When it's possible to run "image show-unwind" without a running +# process, we can remove the unsupported line below, and hard-code an ELF +# triple in the test. +# UNSUPPORTED: system-windows, system-darwin + +# RUN: cd %T +# RUN: %clang_host %S/Inputs/target-symbols-add-unwind.c -g \ +# RUN: -fno-unwind-tables -fno-asynchronous-unwind-tables \ +# RUN: -o target-symbols-add-unwind.debug +# RUN: llvm-objcopy --strip-debug target-symbols-add-unwind.debug \ +# RUN: target-symbols-add-unwind.stripped +# RUN: %lldb target-symbols-add-unwind.stripped -s %s -o quit | FileCheck %s + +process launch --stop-at-entry +image show-unwind -n main +# CHECK-LABEL: image show-unwind -n main +# CHECK-NOT: debug_frame UnwindPlan: + +target symbols add -s target-symbols-add-unwind.stripped target-symbols-add-unwind.debug +# CHECK-LABEL: target symbols add +# CHECK: symbol file {{.*}} has been added to {{.*}} + +image show-unwind -n main +# CHECK-LABEL: image show-unwind -n main +# CHECK: debug_frame UnwindPlan: +# CHECK-NEXT: This UnwindPlan originally sourced from DWARF CFI +# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes. -- GitLab From 468c6bea2280491283e45239ad1c0ac6a59b3da8 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 16:23:46 +0000 Subject: [PATCH 078/541] Fix "result of 32-bit shift implicitly converted to 64 bits" MSVC warning. NFCI. --- llvm/lib/Object/GOFFObjectFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp index 6b48d464dc3e..2845d9362544 100644 --- a/llvm/lib/Object/GOFFObjectFile.cpp +++ b/llvm/lib/Object/GOFFObjectFile.cpp @@ -514,7 +514,7 @@ uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); GOFF::ESDAlignment Pow2Alignment; ESDRecord::getAlignment(EsdRecord, Pow2Alignment); - return 1 << static_cast(Pow2Alignment); + return 1ULL << static_cast(Pow2Alignment); } bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const { -- GitLab From f92fa7e2cf38341211af262b21c568bef4d76b10 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 16:25:55 +0000 Subject: [PATCH 079/541] [X86] Add -verify-machineinstrs to huge stack tests Help identify EXPENSIVE_CHECKS regressions identified in #84114 --- llvm/test/CodeGen/X86/huge-stack-offset.ll | 4 ++-- llvm/test/CodeGen/X86/huge-stack-offset2.ll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/test/CodeGen/X86/huge-stack-offset.ll b/llvm/test/CodeGen/X86/huge-stack-offset.ll index 68dcfa748b0c..e825328ccd89 100644 --- a/llvm/test/CodeGen/X86/huge-stack-offset.ll +++ b/llvm/test/CodeGen/X86/huge-stack-offset.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -mtriple=x86_64-linux-unknown | FileCheck %s --check-prefix=CHECK-64 -; RUN: llc < %s -mtriple=i386-linux-unknown | FileCheck %s --check-prefix=CHECK-32 +; RUN: llc < %s -mtriple=x86_64-linux-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-64 +; RUN: llc < %s -mtriple=i386-linux-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-32 ; Test that a large stack offset uses a single add/sub instruction to ; adjust the stack pointer. diff --git a/llvm/test/CodeGen/X86/huge-stack-offset2.ll b/llvm/test/CodeGen/X86/huge-stack-offset2.ll index 3bf0260cc12a..053643eb3686 100644 --- a/llvm/test/CodeGen/X86/huge-stack-offset2.ll +++ b/llvm/test/CodeGen/X86/huge-stack-offset2.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s --check-prefix=CHECK +; RUN: llc < %s -mtriple=x86_64-linux -verify-machineinstrs | FileCheck %s --check-prefix=CHECK ; Test how we handle pathologically large stack frames when RAX is live through ; the prologue and epilogue. -- GitLab From 9669aba13295de5ccdefc44e22e30c0295e6afd2 Mon Sep 17 00:00:00 2001 From: AtariDreams Date: Wed, 27 Mar 2024 12:33:56 -0400 Subject: [PATCH 080/541] [Thumb1] LivePhysRegs to LiveRegUnits (#84474) This removes the r7 exception because otherwise, LiveRegUnits will try to use that register. --- llvm/lib/Target/ARM/Thumb1FrameLowering.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp index 0f4ece64bff5..047c6731333c 100644 --- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -612,11 +612,11 @@ bool Thumb1FrameLowering::needPopSpecialFixUp(const MachineFunction &MF) const { static void findTemporariesForLR(const BitVector &GPRsNoLRSP, const BitVector &PopFriendly, - const LivePhysRegs &UsedRegs, unsigned &PopReg, + const LiveRegUnits &UsedRegs, unsigned &PopReg, unsigned &TmpReg, MachineRegisterInfo &MRI) { PopReg = TmpReg = 0; for (auto Reg : GPRsNoLRSP.set_bits()) { - if (UsedRegs.available(MRI, Reg)) { + if (UsedRegs.available(Reg)) { // Remember the first pop-friendly register and exit. if (PopFriendly.test(Reg)) { PopReg = Reg; @@ -684,7 +684,7 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, // Look for a temporary register to use. // First, compute the liveness information. const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); - LivePhysRegs UsedRegs(TRI); + LiveRegUnits UsedRegs(TRI); UsedRegs.addLiveOuts(MBB); // The semantic of pristines changed recently and now, // the callee-saved registers that are touched in the function @@ -710,11 +710,6 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, unsigned TemporaryReg = 0; BitVector PopFriendly = TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::tGPRRegClassID)); - // R7 may be used as a frame pointer, hence marked as not generally - // allocatable, however there's no reason to not use it as a temporary for - // restoring LR. - if (STI.getFramePointerReg() == ARM::R7) - PopFriendly.set(ARM::R7); assert(PopFriendly.any() && "No allocatable pop-friendly register?!"); // Rebuild the GPRs from the high registers because they are removed -- GitLab From 6ad1cf3b37f0eefa5f43f90990ec3dcf5c87dead Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Wed, 27 Mar 2024 12:34:21 -0400 Subject: [PATCH 081/541] [InstallAPI] Add *umbrella-header options (#86587) Umbrella headers are a concept for Darwin-based libraries. They allow framework authors to control the order in which their headers should be parsed and allow clients to access available headers by including a single header. InstallAPI will attempt to find the umbrella based on the name of the framework. Users can also specify this explicitly by using command line options specifying the umbrella header by file path. There can be an umbrella header per access level. --- .../clang/Basic/DiagnosticInstallAPIKinds.td | 1 + clang/include/clang/InstallAPI/HeaderFile.h | 16 ++-- .../Umbrella/Umbrella.framework/Headers/AAA.h | 3 + .../Headers/SpecialUmbrella.h | 1 + .../PrivateHeaders/AAA_Private.h | 3 + .../PrivateHeaders/SpecialPrivateUmbrella.h | 1 + .../InstallAPI/umbrella-headers-unix.test | 40 ++++++++++ clang/test/InstallAPI/umbrella-headers.test | 48 +++++++++++ .../tools/clang-installapi/InstallAPIOpts.td | 12 +++ clang/tools/clang-installapi/Options.cpp | 79 ++++++++++++++++++- clang/tools/clang-installapi/Options.h | 9 +++ 11 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h create mode 100644 clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h create mode 100644 clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h create mode 100644 clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h create mode 100644 clang/test/InstallAPI/umbrella-headers-unix.test create mode 100644 clang/test/InstallAPI/umbrella-headers.test diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td index 27df731fa286..e3263fe9ccb9 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -18,6 +18,7 @@ def err_no_output_file: Error<"no output file specified">; def err_no_such_header_file : Error<"no such %select{public|private|project}1 header file: '%0'">; def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public|private}0 header file: '%1'">, InGroup; def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup; +def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">; } // end of command line category. let CategoryName = "Verification" in { diff --git a/clang/include/clang/InstallAPI/HeaderFile.h b/clang/include/clang/InstallAPI/HeaderFile.h index 235b4da3add8..c67503d4ad49 100644 --- a/clang/include/clang/InstallAPI/HeaderFile.h +++ b/clang/include/clang/InstallAPI/HeaderFile.h @@ -24,8 +24,6 @@ namespace clang::installapi { enum class HeaderType { - /// Unset or unknown type. - Unknown, /// Represents declarations accessible to all clients. Public, /// Represents declarations accessible to a disclosed set of clients. @@ -33,6 +31,8 @@ enum class HeaderType { /// Represents declarations only accessible as implementation details to the /// input library. Project, + /// Unset or unknown type. + Unknown, }; inline StringRef getName(const HeaderType T) { @@ -62,6 +62,8 @@ class HeaderFile { bool Excluded{false}; /// Add header file to processing. bool Extra{false}; + /// Specify that header file is the umbrella header for library. + bool Umbrella{false}; public: HeaderFile() = delete; @@ -79,17 +81,21 @@ public: void setExtra(bool V = true) { Extra = V; } void setExcluded(bool V = true) { Excluded = V; } + void setUmbrellaHeader(bool V = true) { Umbrella = V; } bool isExtra() const { return Extra; } bool isExcluded() const { return Excluded; } + bool isUmbrellaHeader() const { return Umbrella; } bool useIncludeName() const { return Type != HeaderType::Project && !IncludeName.empty(); } bool operator==(const HeaderFile &Other) const { - return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra) == - std::tie(Other.Type, Other.FullPath, Other.IncludeName, - Other.Language, Other.Excluded, Other.Extra); + return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra, + Umbrella) == std::tie(Other.Type, Other.FullPath, + Other.IncludeName, Other.Language, + Other.Excluded, Other.Extra, + Other.Umbrella); } }; diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h new file mode 100644 index 000000000000..993d5d4abadb --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h @@ -0,0 +1,3 @@ +#ifndef PUBLIC_UMBRELLA_HEADER_FIRST +#error "Public umbrella header was not included first!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h new file mode 100644 index 000000000000..2599ff14ae17 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h @@ -0,0 +1 @@ +#define PUBLIC_UMBRELLA_HEADER_FIRST diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h new file mode 100644 index 000000000000..557209bfeb86 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h @@ -0,0 +1,3 @@ +#ifndef PRIVATE_UMBRELLA_HEADER_FIRST +#error "Private umbrella header was not included first!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h new file mode 100644 index 000000000000..fd5b49b94316 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h @@ -0,0 +1 @@ +#define PRIVATE_UMBRELLA_HEADER_FIRST diff --git a/clang/test/InstallAPI/umbrella-headers-unix.test b/clang/test/InstallAPI/umbrella-headers-unix.test new file mode 100644 index 000000000000..46118779896c --- /dev/null +++ b/clang/test/InstallAPI/umbrella-headers-unix.test @@ -0,0 +1,40 @@ +// UNSUPPORTED: system-windows + +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: mkdir %t/Frameworks/ +; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/ + +// Only validate path based input that rely on regex matching on unix based file systems. +; RUN: clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella2.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=%t/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h \ +; RUN: -private-umbrella-header \ +; RUN: %t/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s + +; CHECK-NOT: error +; CHECK-NOT: warning + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h", + "type" : "private" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h", + "type" : "private" + }], + "version": "3" +} diff --git a/clang/test/InstallAPI/umbrella-headers.test b/clang/test/InstallAPI/umbrella-headers.test new file mode 100644 index 000000000000..ce9c50608c41 --- /dev/null +++ b/clang/test/InstallAPI/umbrella-headers.test @@ -0,0 +1,48 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/ + +// Check base filename matches. +; RUN: clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=SpecialUmbrella.h \ +; RUN: --private-umbrella-header=SpecialPrivateUmbrella.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s + +// Try missing umbrella header argument. +; RUN: not clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=Ignore.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck %s -check-prefix=ERR + +; ERR: error: public umbrella header file not found in input: 'Ignore.h' + +; CHECK-NOT: error +; CHECK-NOT: warning + +;--- Frameworks/Umbrella.framework/Headers/Ignore.h +#error "This header should be ignored" + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h", + "type" : "private" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h", + "type" : "private" + }], + "version": "3" +} diff --git a/clang/tools/clang-installapi/InstallAPIOpts.td b/clang/tools/clang-installapi/InstallAPIOpts.td index ab9e1fe7f2f9..71532c9cf24d 100644 --- a/clang/tools/clang-installapi/InstallAPIOpts.td +++ b/clang/tools/clang-installapi/InstallAPIOpts.td @@ -61,3 +61,15 @@ def exclude_private_header : Separate<["-"], "exclude-private-header">, HelpText<"Exclude private header from parsing">; def exclude_private_header_EQ : Joined<["--"], "exclude-private-header=">, Alias; +def public_umbrella_header : Separate<["-"], "public-umbrella-header">, + MetaVarName<"">, HelpText<"Specify the public umbrella header location">; +def public_umbrella_header_EQ : Joined<["--"], "public-umbrella-header=">, + Alias; +def private_umbrella_header : Separate<["-"], "private-umbrella-header">, + MetaVarName<"">, HelpText<"Specify the private umbrella header location">; +def private_umbrella_header_EQ : Joined<["--"], "private-umbrella-header=">, + Alias; +def project_umbrella_header : Separate<["-"], "project-umbrella-header">, + MetaVarName<"">, HelpText<"Specify the project umbrella header location">; +def project_umbrella_header_EQ : Joined<["--"], "project-umbrella-header=">, + Alias; diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index 4f79c62724a6..8e4a1b019fd8 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -270,6 +270,16 @@ Options::processAndFilterOutInstallAPIOptions(ArrayRef Args) { OPT_exclude_project_header)) return {}; + // Handle umbrella headers. + if (const Arg *A = ParsedArgs.getLastArg(OPT_public_umbrella_header)) + DriverOpts.PublicUmbrellaHeader = A->getValue(); + + if (const Arg *A = ParsedArgs.getLastArg(OPT_private_umbrella_header)) + DriverOpts.PrivateUmbrellaHeader = A->getValue(); + + if (const Arg *A = ParsedArgs.getLastArg(OPT_project_umbrella_header)) + DriverOpts.ProjectUmbrellaHeader = A->getValue(); + /// Any unclaimed arguments should be forwarded to the clang driver. std::vector ClangDriverArgs(ParsedArgs.size()); for (const Arg *A : ParsedArgs) { @@ -323,6 +333,15 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM, } } +static const Regex Rule("(.+)/(.+)\\.framework/"); +static StringRef getFrameworkNameFromInstallName(StringRef InstallName) { + SmallVector Match; + Rule.match(InstallName, &Match); + if (Match.empty()) + return ""; + return Match.back(); +} + InstallAPIContext Options::createContext() { InstallAPIContext Ctx; Ctx.FM = FM; @@ -339,6 +358,11 @@ InstallAPIContext Options::createContext() { Ctx.OutputLoc = DriverOpts.OutputPath; Ctx.LangMode = FEOpts.LangMode; + // Attempt to find umbrella headers by capturing framework name. + StringRef FrameworkName; + if (!LinkerOpts.IsDylib) + FrameworkName = getFrameworkNameFromInstallName(LinkerOpts.InstallName); + // Process inputs. for (const std::string &ListPath : DriverOpts.FileLists) { auto Buffer = FM->getBufferForFile(ListPath); @@ -357,8 +381,7 @@ InstallAPIContext Options::createContext() { assert(Type != HeaderType::Unknown && "Missing header type."); for (const StringRef Path : Headers) { if (!FM->getOptionalFileRef(Path)) { - Diags->Report(diag::err_no_such_header_file) - << Path << (unsigned)Type - 1; + Diags->Report(diag::err_no_such_header_file) << Path << (unsigned)Type; return false; } SmallString FullPath(Path); @@ -382,6 +405,7 @@ InstallAPIContext Options::createContext() { std::vector> ExcludedHeaderGlobs; std::set ExcludedHeaderFiles; auto ParseGlobs = [&](const PathSeq &Paths, HeaderType Type) { + assert(Type != HeaderType::Unknown && "Missing header type."); for (const StringRef Path : Paths) { auto Glob = HeaderGlob::create(Path, Type); if (Glob) @@ -424,6 +448,57 @@ InstallAPIContext Options::createContext() { if (!Glob->didMatch()) Diags->Report(diag::warn_glob_did_not_match) << Glob->str(); + // Mark any explicit or inferred umbrella headers. If one exists, move + // that to the beginning of the input headers. + auto MarkandMoveUmbrellaInHeaders = [&](llvm::Regex &Regex, + HeaderType Type) -> bool { + auto It = find_if(Ctx.InputHeaders, [&Regex, Type](const HeaderFile &H) { + return (H.getType() == Type) && Regex.match(H.getPath()); + }); + + if (It == Ctx.InputHeaders.end()) + return false; + It->setUmbrellaHeader(); + + // Because there can be an umbrella header per header type, + // find the first non umbrella header to swap position with. + auto BeginPos = find_if(Ctx.InputHeaders, [](const HeaderFile &H) { + return !H.isUmbrellaHeader(); + }); + if (BeginPos != Ctx.InputHeaders.end() && BeginPos < It) + std::swap(*BeginPos, *It); + return true; + }; + + auto FindUmbrellaHeader = [&](StringRef HeaderPath, HeaderType Type) -> bool { + assert(Type != HeaderType::Unknown && "Missing header type."); + if (!HeaderPath.empty()) { + auto EscapedString = Regex::escape(HeaderPath); + Regex UmbrellaRegex(EscapedString); + if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type)) { + Diags->Report(diag::err_no_such_umbrella_header_file) + << HeaderPath << (unsigned)Type; + return false; + } + } else if (!FrameworkName.empty() && (Type != HeaderType::Project)) { + auto UmbrellaName = "/" + Regex::escape(FrameworkName); + if (Type == HeaderType::Public) + UmbrellaName += "\\.h"; + else + UmbrellaName += "[_]?Private\\.h"; + Regex UmbrellaRegex(UmbrellaName); + MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type); + } + return true; + }; + if (!FindUmbrellaHeader(DriverOpts.PublicUmbrellaHeader, + HeaderType::Public) || + !FindUmbrellaHeader(DriverOpts.PrivateUmbrellaHeader, + HeaderType::Private) || + !FindUmbrellaHeader(DriverOpts.ProjectUmbrellaHeader, + HeaderType::Project)) + return Ctx; + // Parse binary dylib and initialize verifier. if (DriverOpts.DylibToVerify.empty()) { Ctx.Verifier = std::make_unique(); diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index c18309f69370..3671e4c8274b 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -31,6 +31,15 @@ struct DriverOptions { /// \brief Path to input file lists (JSON). llvm::MachO::PathSeq FileLists; + /// \brief Path to public umbrella header. + std::string PublicUmbrellaHeader; + + /// \brief Path to private umbrella header. + std::string PrivateUmbrellaHeader; + + /// \brief Path to project umbrella header. + std::string ProjectUmbrellaHeader; + /// \brief Paths of extra public headers. PathSeq ExtraPublicHeaders; -- GitLab From 0099c584bad3bdeb62fede61fb89fdcc022bd2a0 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Wed, 27 Mar 2024 09:35:45 -0700 Subject: [PATCH 082/541] [bazel] Remove -lm on macOS (#86706) Bazel links this library by default which leads to this linker warning on macOS: ``` ld: warning: ignoring duplicate libraries: '-lm' ``` --- utils/bazel/llvm-project-overlay/llvm/BUILD.bazel | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index 0e658353c36f..3c3e17bfec66 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -292,6 +292,10 @@ cc_library( "-ldl", "-lm", ], + "@platforms//os:macos": [ + "-pthread", + "-ldl", + ], "//conditions:default": [ "-pthread", "-ldl", -- GitLab From fca48312a833464369ce1615c60e09f1d71e4aad Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 16:35:46 +0000 Subject: [PATCH 083/541] Fix signed/unsigned comparison warning. NFC. --- compiler-rt/lib/scudo/standalone/tests/strings_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp index e068c48fc97c..3e41f67ba922 100644 --- a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp @@ -141,7 +141,7 @@ TEST(ScudoStringsTest, CapacityIncreaseFails) { // Test requires that the default length is at least 6 characters. scudo::uptr MaxSize = Str.capacity(); - EXPECT_LE(6, MaxSize); + EXPECT_LE(6u, MaxSize); for (size_t i = 0; i < MaxSize - 5; i++) { Str.append("B"); -- GitLab From 4d177435bae03551245ffdc4dfcee5345323121d Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 27 Mar 2024 11:37:09 -0500 Subject: [PATCH 084/541] [flang][OpenMP] Rename makeList overloads to make{Objects,Clauses}, NFC (#86725) Reserve `makeList` to create a list given an explicit converter function. --- flang/lib/Lower/OpenMP/ClauseProcessor.h | 2 +- flang/lib/Lower/OpenMP/Clauses.cpp | 52 +++++++++---------- flang/lib/Lower/OpenMP/Clauses.h | 8 +-- flang/lib/Lower/OpenMP/DataSharingProcessor.h | 2 +- flang/lib/Lower/OpenMP/OpenMP.cpp | 4 +- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index c0c603feb296..d31d6a5c2062 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -51,7 +51,7 @@ public: Fortran::semantics::SemanticsContext &semaCtx, const Fortran::parser::OmpClauseList &clauses) : converter(converter), semaCtx(semaCtx), - clauses(makeList(clauses, semaCtx)) {} + clauses(makeClauses(clauses, semaCtx)) {} // 'Unique' clauses: They can appear at most once in the clause list. bool processCollapse( diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index f48e84f511a4..853dcd78e266 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -347,7 +347,7 @@ Aligned make(const parser::OmpClause::Aligned &inp, return Aligned{{ /*Alignment=*/maybeApply(makeExprFn(semaCtx), t1), - /*List=*/makeList(t0, semaCtx), + /*List=*/makeObjects(t0, semaCtx), }}; } @@ -362,7 +362,7 @@ Allocate make(const parser::OmpClause::Allocate &inp, return Allocate{{/*AllocatorSimpleModifier=*/std::nullopt, /*AllocatorComplexModifier=*/std::nullopt, /*AlignModifier=*/std::nullopt, - /*List=*/makeList(t1, semaCtx)}}; + /*List=*/makeObjects(t1, semaCtx)}}; } using Tuple = decltype(Allocate::t); @@ -374,7 +374,7 @@ Allocate make(const parser::OmpClause::Allocate &inp, return {/*AllocatorSimpleModifier=*/makeExpr(v.v, semaCtx), /*AllocatorComplexModifier=*/std::nullopt, /*AlignModifier=*/std::nullopt, - /*List=*/makeList(t1, semaCtx)}; + /*List=*/makeObjects(t1, semaCtx)}; }, // complex-modifier + align-modifier [&](const wrapped::AllocateModifier::ComplexModifier &v) -> Tuple { @@ -384,14 +384,14 @@ Allocate make(const parser::OmpClause::Allocate &inp, /*AllocatorSimpleModifier=*/std::nullopt, /*AllocatorComplexModifier=*/Allocator{makeExpr(s0.v, semaCtx)}, /*AlignModifier=*/Align{makeExpr(s1.v, semaCtx)}, - /*List=*/makeList(t1, semaCtx)}; + /*List=*/makeObjects(t1, semaCtx)}; }, // align-modifier [&](const wrapped::AllocateModifier::Align &v) -> Tuple { return {/*AllocatorSimpleModifier=*/std::nullopt, /*AllocatorComplexModifier=*/std::nullopt, /*AlignModifier=*/Align{makeExpr(v.v, semaCtx)}, - /*List=*/makeList(t1, semaCtx)}; + /*List=*/makeObjects(t1, semaCtx)}; }, }, t0->u)}; @@ -450,13 +450,13 @@ Collapse make(const parser::OmpClause::Collapse &inp, Copyin make(const parser::OmpClause::Copyin &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return Copyin{/*List=*/makeList(inp.v, semaCtx)}; + return Copyin{/*List=*/makeObjects(inp.v, semaCtx)}; } Copyprivate make(const parser::OmpClause::Copyprivate &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return Copyprivate{/*List=*/makeList(inp.v, semaCtx)}; + return Copyprivate{/*List=*/makeObjects(inp.v, semaCtx)}; } Default make(const parser::OmpClause::Default &inp, @@ -641,7 +641,7 @@ Doacross make(const parser::OmpClause::Doacross &inp, Enter make(const parser::OmpClause::Enter &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return Enter{makeList(/*List=*/inp.v, semaCtx)}; + return Enter{makeObjects(/*List=*/inp.v, semaCtx)}; } Exclusive make(const parser::OmpClause::Exclusive &inp, @@ -671,7 +671,7 @@ Final make(const parser::OmpClause::Final &inp, Firstprivate make(const parser::OmpClause::Firstprivate &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return Firstprivate{/*List=*/makeList(inp.v, semaCtx)}; + return Firstprivate{/*List=*/makeObjects(inp.v, semaCtx)}; } // Flush: empty @@ -681,7 +681,7 @@ From make(const parser::OmpClause::From &inp, // inp.v -> parser::OmpObjectList return From{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, - /*LocatorList=*/makeList(inp.v, semaCtx)}}; + /*LocatorList=*/makeObjects(inp.v, semaCtx)}}; } // Full: empty @@ -696,7 +696,7 @@ Grainsize make(const parser::OmpClause::Grainsize &inp, HasDeviceAddr make(const parser::OmpClause::HasDeviceAddr &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return HasDeviceAddr{/*List=*/makeList(inp.v, semaCtx)}; + return HasDeviceAddr{/*List=*/makeObjects(inp.v, semaCtx)}; } Hint make(const parser::OmpClause::Hint &inp, @@ -762,20 +762,20 @@ InReduction make(const parser::OmpClause::InReduction &inp, auto &t1 = std::get(inp.v.t); return InReduction{ {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, - /*List=*/makeList(t1, semaCtx)}}; + /*List=*/makeObjects(t1, semaCtx)}}; } IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return IsDevicePtr{/*List=*/makeList(inp.v, semaCtx)}; + return IsDevicePtr{/*List=*/makeObjects(inp.v, semaCtx)}; } Lastprivate make(const parser::OmpClause::Lastprivate &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList return Lastprivate{{/*LastprivateModifier=*/std::nullopt, - /*List=*/makeList(inp.v, semaCtx)}}; + /*List=*/makeObjects(inp.v, semaCtx)}}; } Linear make(const parser::OmpClause::Linear &inp, @@ -817,7 +817,7 @@ Linear make(const parser::OmpClause::Linear &inp, Link make(const parser::OmpClause::Link &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return Link{/*List=*/makeList(inp.v, semaCtx)}; + return Link{/*List=*/makeObjects(inp.v, semaCtx)}; } Map make(const parser::OmpClause::Map &inp, @@ -844,7 +844,7 @@ Map make(const parser::OmpClause::Map &inp, if (!t0) { return Map{{/*MapType=*/std::nullopt, /*MapTypeModifiers=*/std::nullopt, /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, - /*LocatorList=*/makeList(t1, semaCtx)}}; + /*LocatorList=*/makeObjects(t1, semaCtx)}}; } auto &s0 = std::get>(t0->t); @@ -857,7 +857,7 @@ Map make(const parser::OmpClause::Map &inp, return Map{{/*MapType=*/convert1(s1), /*MapTypeModifiers=*/maybeList, /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, - /*LocatorList=*/makeList(t1, semaCtx)}}; + /*LocatorList=*/makeObjects(t1, semaCtx)}}; } // Match: incomplete @@ -980,7 +980,7 @@ Priority make(const parser::OmpClause::Priority &inp, Private make(const parser::OmpClause::Private &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return Private{/*List=*/makeList(inp.v, semaCtx)}; + return Private{/*List=*/makeObjects(inp.v, semaCtx)}; } ProcBind make(const parser::OmpClause::ProcBind &inp, @@ -1010,7 +1010,7 @@ Reduction make(const parser::OmpClause::Reduction &inp, return Reduction{ {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, /*ReductionModifier=*/std::nullopt, - /*List=*/makeList(t1, semaCtx)}}; + /*List=*/makeObjects(t1, semaCtx)}}; } // Relaxed: empty @@ -1104,7 +1104,7 @@ Severity make(const parser::OmpClause::Severity &inp, Shared make(const parser::OmpClause::Shared &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return Shared{/*List=*/makeList(inp.v, semaCtx)}; + return Shared{/*List=*/makeObjects(inp.v, semaCtx)}; } // Simd: empty @@ -1128,7 +1128,7 @@ TaskReduction make(const parser::OmpClause::TaskReduction &inp, auto &t1 = std::get(inp.v.t); return TaskReduction{ {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, - /*List=*/makeList(t1, semaCtx)}}; + /*List=*/makeObjects(t1, semaCtx)}}; } ThreadLimit make(const parser::OmpClause::ThreadLimit &inp, @@ -1145,7 +1145,7 @@ To make(const parser::OmpClause::To &inp, // inp.v -> parser::OmpObjectList return To{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, - /*LocatorList=*/makeList(inp.v, semaCtx)}}; + /*LocatorList=*/makeObjects(inp.v, semaCtx)}}; } // UnifiedAddress: empty @@ -1175,13 +1175,13 @@ Use make(const parser::OmpClause::Use &inp, UseDeviceAddr make(const parser::OmpClause::UseDeviceAddr &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return UseDeviceAddr{/*List=*/makeList(inp.v, semaCtx)}; + return UseDeviceAddr{/*List=*/makeObjects(inp.v, semaCtx)}; } UseDevicePtr make(const parser::OmpClause::UseDevicePtr &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpObjectList - return UseDevicePtr{/*List=*/makeList(inp.v, semaCtx)}; + return UseDevicePtr{/*List=*/makeObjects(inp.v, semaCtx)}; } UsesAllocators make(const parser::OmpClause::UsesAllocators &inp, @@ -1205,8 +1205,8 @@ Clause makeClause(const Fortran::parser::OmpClause &cls, cls.u); } -List makeList(const parser::OmpClauseList &clauses, - semantics::SemanticsContext &semaCtx) { +List makeClauses(const parser::OmpClauseList &clauses, + semantics::SemanticsContext &semaCtx) { return makeList(clauses.v, [&](const parser::OmpClause &s) { return makeClause(s, semaCtx); }); diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h index af1318226e8c..3e776425c733 100644 --- a/flang/lib/Lower/OpenMP/Clauses.h +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -88,8 +88,8 @@ List makeList(ContainerTy &&container, FunctionTy &&func) { return v; } -inline ObjectList makeList(const parser::OmpObjectList &objects, - semantics::SemanticsContext &semaCtx) { +inline ObjectList makeObjects(const parser::OmpObjectList &objects, + semantics::SemanticsContext &semaCtx) { return makeList(objects.v, makeObjectFn(semaCtx)); } @@ -256,8 +256,8 @@ Clause makeClause(llvm::omp::Clause id, Specific &&specific, Clause makeClause(const Fortran::parser::OmpClause &cls, semantics::SemanticsContext &semaCtx); -List makeList(const parser::OmpClauseList &clauses, - semantics::SemanticsContext &semaCtx); +List makeClauses(const parser::OmpClauseList &clauses, + semantics::SemanticsContext &semaCtx); } // namespace Fortran::lower::omp #endif // FORTRAN_LOWER_OPENMP_CLAUSES_H diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h index 226abe96705e..1cbc825fd5e1 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h @@ -89,7 +89,7 @@ public: Fortran::lower::SymMap *symTable = nullptr) : hasLastPrivateOp(false), converter(converter), firOpBuilder(converter.getFirOpBuilder()), - clauses(omp::makeList(opClauseList, semaCtx)), eval(eval), + clauses(omp::makeClauses(opClauseList, semaCtx)), eval(eval), useDelayedPrivatization(useDelayedPrivatization), symTable(symTable) {} // Privatisation is split into two steps. diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 0cf2a8f97040..5defffd738b4 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -1254,7 +1254,7 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo( if (const auto *objectList{ Fortran::parser::Unwrap(spec.u)}) { - ObjectList objects{makeList(*objectList, semaCtx)}; + ObjectList objects{makeObjects(*objectList, semaCtx)}; // Case: declare target(func, var1, var2) gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to, symbolAndClause); @@ -2352,7 +2352,7 @@ void Fortran::lower::genOpenMPReduction( const Fortran::parser::OmpClauseList &clauseList) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - List clauses{makeList(clauseList, semaCtx)}; + List clauses{makeClauses(clauseList, semaCtx)}; for (const Clause &clause : clauses) { if (const auto &reductionClause = -- GitLab From 1c965801c42c92ff0b768e31348285514ecf5511 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Mar 2024 09:39:35 -0700 Subject: [PATCH 085/541] [LegalizeDAG] Merge PerformInsertVectorEltInMemory into ExpandInsertToVectorThroughStack. NFC (#86755) These functions are very similar. We can share them like we do for EXTRACT_VECTOR_ELT and EXTRACT_SUBVECTOR. --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 83 ++++++------------- 1 file changed, 26 insertions(+), 57 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index b1f6fd6f3c72..e10b8bc8c5e2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -118,14 +118,7 @@ private: void LegalizeLoadOps(SDNode *Node); void LegalizeStoreOps(SDNode *Node); - /// Some targets cannot handle a variable - /// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it - /// is necessary to spill the vector being inserted into to memory, perform - /// the insert there, and then read the result back. - SDValue PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, - const SDLoc &dl); - SDValue ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, SDValue Idx, - const SDLoc &dl); + SDValue ExpandINSERT_VECTOR_ELT(SDValue Op); /// Return a vector shuffle operation which /// performs the same shuffe in terms of order or result bytes, but on a type @@ -378,45 +371,12 @@ SDValue SelectionDAGLegalize::ExpandConstant(ConstantSDNode *CP) { return Result; } -/// Some target cannot handle a variable insertion index for the -/// INSERT_VECTOR_ELT instruction. In this case, it -/// is necessary to spill the vector being inserted into to memory, perform -/// the insert there, and then read the result back. -SDValue SelectionDAGLegalize::PerformInsertVectorEltInMemory(SDValue Vec, - SDValue Val, - SDValue Idx, - const SDLoc &dl) { - // If the target doesn't support this, we have to spill the input vector - // to a temporary stack slot, update the element, then reload it. This is - // badness. We could also load the value into a vector register (either - // with a "move to register" or "extload into register" instruction, then - // permute it into place, if the idx is a constant and if the idx is - // supported by the target. - EVT VT = Vec.getValueType(); - EVT EltVT = VT.getVectorElementType(); - SDValue StackPtr = DAG.CreateStackTemporary(VT); - - int SPFI = cast(StackPtr.getNode())->getIndex(); - - // Store the vector. - SDValue Ch = DAG.getStore( - DAG.getEntryNode(), dl, Vec, StackPtr, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI)); - - SDValue StackPtr2 = TLI.getVectorElementPointer(DAG, StackPtr, VT, Idx); - - // Store the scalar value. - Ch = DAG.getTruncStore( - Ch, dl, Val, StackPtr2, - MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT); - // Load the updated vector. - return DAG.getLoad(VT, dl, Ch, StackPtr, MachinePointerInfo::getFixedStack( - DAG.getMachineFunction(), SPFI)); -} +SDValue SelectionDAGLegalize::ExpandINSERT_VECTOR_ELT(SDValue Op) { + SDValue Vec = Op.getOperand(0); + SDValue Val = Op.getOperand(1); + SDValue Idx = Op.getOperand(2); + SDLoc dl(Op); -SDValue SelectionDAGLegalize::ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, - SDValue Idx, - const SDLoc &dl) { if (ConstantSDNode *InsertPos = dyn_cast(Idx)) { // SCALAR_TO_VECTOR requires that the type of the value being inserted // match the element type of the vector being created, except for @@ -438,7 +398,7 @@ SDValue SelectionDAGLegalize::ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, return DAG.getVectorShuffle(Vec.getValueType(), dl, Vec, ScVec, ShufOps); } } - return PerformInsertVectorEltInMemory(Vec, Val, Idx, dl); + return ExpandInsertToVectorThroughStack(Op); } SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { @@ -1486,7 +1446,7 @@ SDValue SelectionDAGLegalize::ExpandInsertToVectorThroughStack(SDValue Op) { // Store the value to a temporary stack slot, then LOAD the returned part. EVT VecVT = Vec.getValueType(); - EVT SubVecVT = Part.getValueType(); + EVT PartVT = Part.getValueType(); SDValue StackPtr = DAG.CreateStackTemporary(VecVT); int FI = cast(StackPtr.getNode())->getIndex(); MachinePointerInfo PtrInfo = @@ -1496,13 +1456,24 @@ SDValue SelectionDAGLegalize::ExpandInsertToVectorThroughStack(SDValue Op) { SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo); // Then store the inserted part. - SDValue SubStackPtr = - TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx); + if (PartVT.isVector()) { + SDValue SubStackPtr = + TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, PartVT, Idx); + + // Store the subvector. + Ch = DAG.getStore( + Ch, dl, Part, SubStackPtr, + MachinePointerInfo::getUnknownStack(DAG.getMachineFunction())); + } else { + SDValue SubStackPtr = + TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx); - // Store the subvector. - Ch = DAG.getStore( - Ch, dl, Part, SubStackPtr, - MachinePointerInfo::getUnknownStack(DAG.getMachineFunction())); + // Store the scalar value. + Ch = DAG.getTruncStore( + Ch, dl, Part, SubStackPtr, + MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), + VecVT.getVectorElementType()); + } // Finally, load the updated vector. return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, PtrInfo); @@ -3416,9 +3387,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) { Results.push_back(ExpandSCALAR_TO_VECTOR(Node)); break; case ISD::INSERT_VECTOR_ELT: - Results.push_back(ExpandINSERT_VECTOR_ELT(Node->getOperand(0), - Node->getOperand(1), - Node->getOperand(2), dl)); + Results.push_back(ExpandINSERT_VECTOR_ELT(SDValue(Node, 0))); break; case ISD::VECTOR_SHUFFLE: { SmallVector NewMask; -- GitLab From c335accb07c0cfa4bd7f47edc94c9005692edfcc Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 27 Mar 2024 09:47:16 -0700 Subject: [PATCH 086/541] [ELF] --pack-dyn-relocs=android+relr: place IRELATIVE in .rela.plt (#86751) Current Bionic processes relocations in this order: * DT_ANDROID_REL[A] * DT_RELR * DT_REL[A] * DT_JMPREL If an IRELATIVE relocation is in DT_ANDROID_REL[A], it would read unrelocated (incorrect) global variables associated with RELR when --pack-dyn-relocs=android+relr is enabled. Work around this by placing IRELATIVE in .rel[a].plt (DT_JMPREL). Link: https://r.android.com/3014185 --- lld/ELF/Relocations.cpp | 11 +++++-- lld/test/ELF/pack-dyn-relocs-ifunc.s | 49 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 lld/test/ELF/pack-dyn-relocs-ifunc.s diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 33c50133bec4..92f2e200db11 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1659,10 +1659,17 @@ static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) { // original section/value pairs. For non-GOT non-PLT relocation case below, we // may alter section/value, so create a copy of the symbol to make // section/value fixed. + // + // Prior to Android V, there was a bug that caused RELR relocations to be + // applied after packed relocations. This meant that resolvers referenced by + // IRELATIVE relocations in the packed relocation section would read + // unrelocated globals with RELR relocations when + // --pack-relative-relocs=android+relr is enabled. Work around this by placing + // IRELATIVE in .rela.plt. auto *directSym = makeDefined(cast(sym)); directSym->allocateAux(); - addPltEntry(*in.iplt, *in.igotPlt, *mainPart->relaDyn, target->iRelativeRel, - *directSym); + auto &dyn = config->androidPackDynRelocs ? *in.relaPlt : *mainPart->relaDyn; + addPltEntry(*in.iplt, *in.igotPlt, dyn, target->iRelativeRel, *directSym); sym.allocateAux(); symAux.back().pltIdx = symAux[directSym->auxIdx].pltIdx; diff --git a/lld/test/ELF/pack-dyn-relocs-ifunc.s b/lld/test/ELF/pack-dyn-relocs-ifunc.s new file mode 100644 index 000000000000..6168d06f99d9 --- /dev/null +++ b/lld/test/ELF/pack-dyn-relocs-ifunc.s @@ -0,0 +1,49 @@ +# REQUIRES: aarch64 +## Prior to Android V, there was a bug that caused RELR relocations to be +## applied after packed relocations. This meant that resolvers referenced by +## IRELATIVE relocations in the packed relocation section would read unrelocated +## globals when --pack-relative-relocs=android+relr is enabled. Work around this +## by placing IRELATIVE in .rela.plt. + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android a.s -o a.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android b.s -o b.o +# RUN: ld.lld -shared b.o -o b.so +# RUN: ld.lld -pie --pack-dyn-relocs=android+relr -z separate-loadable-segments a.o b.so -o a +# RUN: llvm-readobj -r a | FileCheck %s +# RUN: llvm-objdump -d a | FileCheck %s --check-prefix=ASM + +# CHECK: .relr.dyn { +# CHECK-NEXT: 0x30000 R_AARCH64_RELATIVE - +# CHECK-NEXT: } +# CHECK: .rela.plt { +# CHECK-NEXT: 0x30020 R_AARCH64_JUMP_SLOT bar 0x0 +# CHECK-NEXT: 0x30028 R_AARCH64_IRELATIVE - 0x10000 +# CHECK-NEXT: } + +# ASM: <.iplt>: +# ASM-NEXT: adrp x16, 0x30000 +# ASM-NEXT: ldr x17, [x16, #0x28] +# ASM-NEXT: add x16, x16, #0x28 +# ASM-NEXT: br x17 + +#--- a.s +.text +.type foo, %gnu_indirect_function +.globl foo +foo: + ret + +.globl _start +_start: + bl foo + bl bar + +.data +.balign 8 +.quad .data + +#--- b.s +.globl bar +bar: + ret -- GitLab From dcd0f2b6103072b74b446c2d1e9ecec60001a28c Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 17:01:41 +0000 Subject: [PATCH 087/541] [X86] combineExtractFromVectorLoad support extraction from vector of different types to the extraction type/index combineExtractFromVectorLoad no longer uses the vector we're extracting from to determine the pointer offset calculation, allowing us to extract from types that have been bitcast to work with specific target shuffles. Fixes #85419 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 23 +- llvm/test/CodeGen/X86/extractelement-load.ll | 35 +- llvm/test/CodeGen/X86/pr45378.ll | 40 +-- .../test/CodeGen/X86/setcc-non-simple-type.ll | 36 +-- llvm/test/CodeGen/X86/var-permute-128.ll | 32 +- llvm/test/CodeGen/X86/vec_int_to_fp.ll | 305 +++++++----------- 6 files changed, 179 insertions(+), 292 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a229f6e55a98..9d98d31b31df 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -43999,18 +43999,18 @@ static SDValue combineBasicSADPattern(SDNode *Extract, SelectionDAG &DAG, // integer, that requires a potentially expensive XMM -> GPR transfer. // Additionally, if we can convert to a scalar integer load, that will likely // be folded into a subsequent integer op. +// Note: SrcVec might not have a VecVT type, but it must be the same size. // Note: Unlike the related fold for this in DAGCombiner, this is not limited // to a single-use of the loaded vector. For the reasons above, we // expect this to be profitable even if it creates an extra load. static SDValue -combineExtractFromVectorLoad(SDNode *N, SDValue InputVector, uint64_t Idx, +combineExtractFromVectorLoad(SDNode *N, EVT VecVT, SDValue SrcVec, uint64_t Idx, const SDLoc &dl, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI) { assert(N->getOpcode() == ISD::EXTRACT_VECTOR_ELT && "Only EXTRACT_VECTOR_ELT supported so far"); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - EVT SrcVT = InputVector.getValueType(); EVT VT = N->getValueType(0); bool LikelyUsedAsVector = any_of(N->uses(), [](SDNode *Use) { @@ -44019,12 +44019,13 @@ combineExtractFromVectorLoad(SDNode *N, SDValue InputVector, uint64_t Idx, Use->getOpcode() == ISD::SCALAR_TO_VECTOR; }); - auto *LoadVec = dyn_cast(InputVector); + auto *LoadVec = dyn_cast(SrcVec); if (LoadVec && ISD::isNormalLoad(LoadVec) && VT.isInteger() && - SrcVT.getVectorElementType() == VT && DCI.isAfterLegalizeDAG() && - !LikelyUsedAsVector && LoadVec->isSimple()) { + VecVT.getVectorElementType() == VT && + VecVT.getSizeInBits() == SrcVec.getValueSizeInBits() && + DCI.isAfterLegalizeDAG() && !LikelyUsedAsVector && LoadVec->isSimple()) { SDValue NewPtr = TLI.getVectorElementPointer( - DAG, LoadVec->getBasePtr(), SrcVT, DAG.getVectorIdxConstant(Idx, dl)); + DAG, LoadVec->getBasePtr(), VecVT, DAG.getVectorIdxConstant(Idx, dl)); unsigned PtrOff = VT.getSizeInBits() * Idx / 8; MachinePointerInfo MPI = LoadVec->getPointerInfo().getWithOffset(PtrOff); Align Alignment = commonAlignment(LoadVec->getAlign(), PtrOff); @@ -44234,10 +44235,9 @@ static SDValue combineExtractWithShuffle(SDNode *N, SelectionDAG &DAG, if (SDValue V = GetLegalExtract(SrcOp, ExtractVT, ExtractIdx)) return DAG.getZExtOrTrunc(V, dl, VT); - if (N->getOpcode() == ISD::EXTRACT_VECTOR_ELT && ExtractVT == SrcVT && - SrcOp.getValueType() == SrcVT) - if (SDValue V = - combineExtractFromVectorLoad(N, SrcOp, ExtractIdx, dl, DAG, DCI)) + if (N->getOpcode() == ISD::EXTRACT_VECTOR_ELT && ExtractVT == SrcVT) + if (SDValue V = combineExtractFromVectorLoad( + N, SrcVT, peekThroughBitcasts(SrcOp), ExtractIdx, dl, DAG, DCI)) return V; return SDValue(); @@ -44651,7 +44651,8 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG, if (CIdx) if (SDValue V = combineExtractFromVectorLoad( - N, InputVector, CIdx->getZExtValue(), dl, DAG, DCI)) + N, InputVector.getValueType(), InputVector, CIdx->getZExtValue(), + dl, DAG, DCI)) return V; // Attempt to extract a i1 element by using MOVMSK to extract the signbits diff --git a/llvm/test/CodeGen/X86/extractelement-load.ll b/llvm/test/CodeGen/X86/extractelement-load.ll index ba2217f704bd..022b25a24153 100644 --- a/llvm/test/CodeGen/X86/extractelement-load.ll +++ b/llvm/test/CodeGen/X86/extractelement-load.ll @@ -76,11 +76,9 @@ bb: define i64 @t4(ptr %a) { ; X86-SSE2-LABEL: t4: ; X86-SSE2: # %bb.0: -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-SSE2-NEXT: movdqa (%eax), %xmm0 -; X86-SSE2-NEXT: movd %xmm0, %eax -; X86-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X86-SSE2-NEXT: movd %xmm0, %edx +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movl (%ecx), %eax +; X86-SSE2-NEXT: movl 4(%ecx), %edx ; X86-SSE2-NEXT: retl ; ; X64-LABEL: t4: @@ -289,24 +287,15 @@ define i32 @PR85419(ptr %p0) { ; X86-SSE2-NEXT: .LBB8_2: ; X86-SSE2-NEXT: retl ; -; X64-SSSE3-LABEL: PR85419: -; X64-SSSE3: # %bb.0: -; X64-SSSE3-NEXT: xorl %ecx, %ecx -; X64-SSSE3-NEXT: cmpq $0, (%rdi) -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = mem[2,3,2,3] -; X64-SSSE3-NEXT: movd %xmm0, %eax -; X64-SSSE3-NEXT: cmovel %ecx, %eax -; X64-SSSE3-NEXT: retq -; -; X64-AVX-LABEL: PR85419: -; X64-AVX: # %bb.0: -; X64-AVX-NEXT: xorl %eax, %eax -; X64-AVX-NEXT: cmpq $0, (%rdi) -; X64-AVX-NEXT: je .LBB8_2 -; X64-AVX-NEXT: # %bb.1: -; X64-AVX-NEXT: movl 8(%rdi), %eax -; X64-AVX-NEXT: .LBB8_2: -; X64-AVX-NEXT: retq +; X64-LABEL: PR85419: +; X64: # %bb.0: +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: cmpq $0, (%rdi) +; X64-NEXT: je .LBB8_2 +; X64-NEXT: # %bb.1: +; X64-NEXT: movl 8(%rdi), %eax +; X64-NEXT: .LBB8_2: +; X64-NEXT: retq %load = load <2 x i64>, ptr %p0, align 16 %vecext.i = extractelement <2 x i64> %load, i64 0 %cmp = icmp eq i64 %vecext.i, 0 diff --git a/llvm/test/CodeGen/X86/pr45378.ll b/llvm/test/CodeGen/X86/pr45378.ll index 426f4eed662a..6a5770a4b4ad 100644 --- a/llvm/test/CodeGen/X86/pr45378.ll +++ b/llvm/test/CodeGen/X86/pr45378.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefix=SSE2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefix=SSE41 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefix=AVX -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=AVX -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512f | FileCheck %s --check-prefix=AVX -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512bw | FileCheck %s --check-prefix=AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefixes=CHECK,SSE2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE41 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefixes=CHECK,AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefixes=CHECK,AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512f | FileCheck %s --check-prefixes=CHECK,AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512bw | FileCheck %s --check-prefixes=CHECK,AVX declare i64 @llvm.vector.reduce.or.v2i64(<2 x i64>) @@ -71,28 +71,12 @@ define i1 @parseHeaders2_scalar_or(ptr %ptr) nounwind { } define i1 @parseHeaders2_scalar_and(ptr %ptr) nounwind { -; SSE2-LABEL: parseHeaders2_scalar_and: -; SSE2: # %bb.0: -; SSE2-NEXT: movdqu (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rax -; SSE2-NEXT: testq %rax, (%rdi) -; SSE2-NEXT: sete %al -; SSE2-NEXT: retq -; -; SSE41-LABEL: parseHeaders2_scalar_and: -; SSE41: # %bb.0: -; SSE41-NEXT: movq (%rdi), %rax -; SSE41-NEXT: testq %rax, 8(%rdi) -; SSE41-NEXT: sete %al -; SSE41-NEXT: retq -; -; AVX-LABEL: parseHeaders2_scalar_and: -; AVX: # %bb.0: -; AVX-NEXT: movq (%rdi), %rax -; AVX-NEXT: testq %rax, 8(%rdi) -; AVX-NEXT: sete %al -; AVX-NEXT: retq +; CHECK-LABEL: parseHeaders2_scalar_and: +; CHECK: # %bb.0: +; CHECK-NEXT: movq (%rdi), %rax +; CHECK-NEXT: testq %rax, 8(%rdi) +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq %vload = load <2 x i64>, ptr %ptr, align 8 %v1 = extractelement <2 x i64> %vload, i32 0 %v2 = extractelement <2 x i64> %vload, i32 1 diff --git a/llvm/test/CodeGen/X86/setcc-non-simple-type.ll b/llvm/test/CodeGen/X86/setcc-non-simple-type.ll index 2187c653f76c..97c3c2040b29 100644 --- a/llvm/test/CodeGen/X86/setcc-non-simple-type.ll +++ b/llvm/test/CodeGen/X86/setcc-non-simple-type.ll @@ -60,36 +60,30 @@ define void @failing(ptr %0, ptr %1) nounwind { ; CHECK-NEXT: .LBB0_2: # %vector.body ; CHECK-NEXT: # Parent Loop BB0_1 Depth=1 ; CHECK-NEXT: # => This Inner Loop Header: Depth=2 -; CHECK-NEXT: movdqu 1024(%rdx,%rdi), %xmm5 -; CHECK-NEXT: movdqu 1040(%rdx,%rdi), %xmm6 -; CHECK-NEXT: pshufd {{.*#+}} xmm5 = xmm5[2,3,2,3] -; CHECK-NEXT: movq %xmm5, %r8 -; CHECK-NEXT: pshufd {{.*#+}} xmm5 = xmm6[2,3,2,3] -; CHECK-NEXT: movq %xmm5, %r9 -; CHECK-NEXT: cmpq 1040(%rdx,%rdi), %rsi -; CHECK-NEXT: movq %rcx, %r10 -; CHECK-NEXT: sbbq %r9, %r10 -; CHECK-NEXT: setge %r9b -; CHECK-NEXT: movzbl %r9b, %r9d -; CHECK-NEXT: andl $1, %r9d -; CHECK-NEXT: negq %r9 -; CHECK-NEXT: movq %r9, %xmm5 ; CHECK-NEXT: cmpq 1024(%rdx,%rdi), %rsi -; CHECK-NEXT: movq %rcx, %r9 -; CHECK-NEXT: sbbq %r8, %r9 +; CHECK-NEXT: movq %rcx, %r8 +; CHECK-NEXT: sbbq 1032(%rdx,%rdi), %r8 +; CHECK-NEXT: setge %r8b +; CHECK-NEXT: movzbl %r8b, %r8d +; CHECK-NEXT: andl $1, %r8d +; CHECK-NEXT: negq %r8 +; CHECK-NEXT: movq %r8, %xmm5 +; CHECK-NEXT: cmpq 1040(%rdx,%rdi), %rsi +; CHECK-NEXT: movq %rcx, %r8 +; CHECK-NEXT: sbbq 1048(%rdx,%rdi), %r8 ; CHECK-NEXT: setge %r8b ; CHECK-NEXT: movzbl %r8b, %r8d ; CHECK-NEXT: andl $1, %r8d ; CHECK-NEXT: negq %r8 ; CHECK-NEXT: movq %r8, %xmm6 -; CHECK-NEXT: punpcklqdq {{.*#+}} xmm6 = xmm6[0],xmm5[0] -; CHECK-NEXT: movdqa %xmm1, %xmm5 -; CHECK-NEXT: psllq %xmm4, %xmm5 +; CHECK-NEXT: punpcklqdq {{.*#+}} xmm5 = xmm5[0],xmm6[0] +; CHECK-NEXT: movdqa %xmm1, %xmm6 +; CHECK-NEXT: psllq %xmm4, %xmm6 ; CHECK-NEXT: pshufd {{.*#+}} xmm7 = xmm4[2,3,2,3] ; CHECK-NEXT: movdqa %xmm1, %xmm8 ; CHECK-NEXT: psllq %xmm7, %xmm8 -; CHECK-NEXT: movsd {{.*#+}} xmm8 = xmm5[0],xmm8[1] -; CHECK-NEXT: andpd %xmm6, %xmm8 +; CHECK-NEXT: movsd {{.*#+}} xmm8 = xmm6[0],xmm8[1] +; CHECK-NEXT: andpd %xmm5, %xmm8 ; CHECK-NEXT: orpd %xmm8, %xmm3 ; CHECK-NEXT: paddq %xmm2, %xmm4 ; CHECK-NEXT: addq $32, %rdi diff --git a/llvm/test/CodeGen/X86/var-permute-128.ll b/llvm/test/CodeGen/X86/var-permute-128.ll index 99a3821bb9ba..f2240a946844 100644 --- a/llvm/test/CodeGen/X86/var-permute-128.ll +++ b/llvm/test/CodeGen/X86/var-permute-128.ll @@ -1101,17 +1101,13 @@ define <16 x i8> @var_shuffle_v16i8_from_v32i8_v16i8(<32 x i8> %v, <16 x i8> %in define void @indices_convert() { ; SSE3-LABEL: indices_convert: ; SSE3: # %bb.0: # %bb -; SSE3-NEXT: movdqa (%rax), %xmm0 -; SSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] -; SSE3-NEXT: movd %xmm1, %eax -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movaps (%rax), %xmm0 +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movl (%rax), %eax +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) ; SSE3-NEXT: andl $3, %eax -; SSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[3,3,3,3] -; SSE3-NEXT: movd %xmm1, %ecx -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSE3-NEXT: andl $3, %ecx ; SSE3-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; SSE3-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero ; SSE3-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm0[0] @@ -1120,17 +1116,13 @@ define void @indices_convert() { ; ; SSSE3-LABEL: indices_convert: ; SSSE3: # %bb.0: # %bb -; SSSE3-NEXT: movdqa (%rax), %xmm0 -; SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] -; SSSE3-NEXT: movd %xmm1, %eax -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movaps (%rax), %xmm0 +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movl (%rax), %eax +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) ; SSSE3-NEXT: andl $3, %eax -; SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[3,3,3,3] -; SSSE3-NEXT: movd %xmm1, %ecx -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSSE3-NEXT: andl $3, %ecx ; SSSE3-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; SSSE3-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero ; SSSE3-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm0[0] diff --git a/llvm/test/CodeGen/X86/vec_int_to_fp.ll b/llvm/test/CodeGen/X86/vec_int_to_fp.ll index 7bbcdee9a680..e26de4be7066 100644 --- a/llvm/test/CodeGen/X86/vec_int_to_fp.ll +++ b/llvm/test/CodeGen/X86/vec_int_to_fp.ll @@ -2911,23 +2911,12 @@ define <8 x float> @uitofp_16i8_to_8f32(<16 x i8> %a) { ; define <2 x double> @sitofp_load_2i64_to_2f64(ptr%a) { -; SSE2-LABEL: sitofp_load_2i64_to_2f64: -; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2sd %rax, %xmm1 -; SSE2-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE2-NEXT: retq -; -; SSE41-LABEL: sitofp_load_2i64_to_2f64: -; SSE41: # %bb.0: -; SSE41-NEXT: cvtsi2sdq 8(%rdi), %xmm1 -; SSE41-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE41-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE41-NEXT: retq +; SSE-LABEL: sitofp_load_2i64_to_2f64: +; SSE: # %bb.0: +; SSE-NEXT: cvtsi2sdq 8(%rdi), %xmm1 +; SSE-NEXT: cvtsi2sdq (%rdi), %xmm0 +; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE-NEXT: retq ; ; VEX-LABEL: sitofp_load_2i64_to_2f64: ; VEX: # %bb.0: @@ -3093,35 +3082,16 @@ define <2 x double> @sitofp_load_2i8_to_2f64(ptr%a) { } define <4 x double> @sitofp_load_4i64_to_4f64(ptr%a) { -; SSE2-LABEL: sitofp_load_4i64_to_4f64: -; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: movdqa 16(%rdi), %xmm2 -; SSE2-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2sd %rax, %xmm1 -; SSE2-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2sdq 16(%rdi), %xmm1 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2sd %rax, %xmm2 -; SSE2-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] -; SSE2-NEXT: retq -; -; SSE41-LABEL: sitofp_load_4i64_to_4f64: -; SSE41: # %bb.0: -; SSE41-NEXT: cvtsi2sdq 8(%rdi), %xmm1 -; SSE41-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE41-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE41-NEXT: cvtsi2sdq 24(%rdi), %xmm2 -; SSE41-NEXT: xorps %xmm1, %xmm1 -; SSE41-NEXT: cvtsi2sdq 16(%rdi), %xmm1 -; SSE41-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] -; SSE41-NEXT: retq +; SSE-LABEL: sitofp_load_4i64_to_4f64: +; SSE: # %bb.0: +; SSE-NEXT: cvtsi2sdq 8(%rdi), %xmm1 +; SSE-NEXT: cvtsi2sdq (%rdi), %xmm0 +; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE-NEXT: cvtsi2sdq 24(%rdi), %xmm2 +; SSE-NEXT: xorps %xmm1, %xmm1 +; SSE-NEXT: cvtsi2sdq 16(%rdi), %xmm1 +; SSE-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] +; SSE-NEXT: retq ; ; VEX-LABEL: sitofp_load_4i64_to_4f64: ; VEX: # %bb.0: @@ -3865,22 +3835,14 @@ define <4 x double> @uitofp_load_4i8_to_4f64(ptr%a) { define <4 x float> @sitofp_load_4i64_to_4f32(ptr%a) { ; SSE2-LABEL: sitofp_load_4i64_to_4f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm2 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: unpcklps {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 24(%rdi), %xmm0 +; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm1 +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 8(%rdi), %xmm2 ; SSE2-NEXT: xorps %xmm0, %xmm0 ; SSE2-NEXT: cvtsi2ssq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm2[0] +; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] ; SSE2-NEXT: retq ; ; SSE41-LABEL: sitofp_load_4i64_to_4f32: @@ -4015,39 +3977,24 @@ define <4 x float> @sitofp_load_4i8_to_4f32(ptr%a) { define <8 x float> @sitofp_load_8i64_to_8f32(ptr%a) { ; SSE2-LABEL: sitofp_load_8i64_to_8f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: movdqa 32(%rdi), %xmm2 -; SSE2-NEXT: movdqa 48(%rdi), %xmm3 -; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm4 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: unpcklps {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 24(%rdi), %xmm0 +; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm1 +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 8(%rdi), %xmm2 ; SSE2-NEXT: xorps %xmm0, %xmm0 ; SSE2-NEXT: cvtsi2ssq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm4[0] -; SSE2-NEXT: xorps %xmm4, %xmm4 -; SSE2-NEXT: cvtsi2ssq 48(%rdi), %xmm4 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm3[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax +; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] ; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: unpcklps {{.*#+}} xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1] +; SSE2-NEXT: cvtsi2ssq 56(%rdi), %xmm1 +; SSE2-NEXT: xorps %xmm2, %xmm2 +; SSE2-NEXT: cvtsi2ssq 48(%rdi), %xmm2 +; SSE2-NEXT: unpcklps {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1] +; SSE2-NEXT: cvtsi2ssq 40(%rdi), %xmm3 ; SSE2-NEXT: xorps %xmm1, %xmm1 ; SSE2-NEXT: cvtsi2ssq 32(%rdi), %xmm1 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 -; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm4[0] +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1] +; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm2[0] ; SSE2-NEXT: retq ; ; SSE41-LABEL: sitofp_load_8i64_to_8f32: @@ -4256,70 +4203,64 @@ define <8 x float> @sitofp_load_8i8_to_8f32(ptr%a) { define <4 x float> @uitofp_load_4i64_to_4f32(ptr%a) { ; SSE2-LABEL: uitofp_load_4i64_to_4f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: movq 24(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB83_1 ; SSE2-NEXT: # %bb.2: -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: jmp .LBB83_3 ; SSE2-NEXT: .LBB83_1: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: addss %xmm1, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 +; SSE2-NEXT: addss %xmm0, %xmm0 ; SSE2-NEXT: .LBB83_3: -; SSE2-NEXT: movq (%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rcx -; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB83_4 ; SSE2-NEXT: # %bb.5: -; SSE2-NEXT: cvtsi2ss %rcx, %xmm2 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: jmp .LBB83_6 ; SSE2-NEXT: .LBB83_4: +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: shrq %rcx +; SSE2-NEXT: andl $1, %eax +; SSE2-NEXT: orq %rcx, %rax +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: addss %xmm1, %xmm1 +; SSE2-NEXT: .LBB83_6: +; SSE2-NEXT: movq (%rdi), %rax +; SSE2-NEXT: movq 8(%rdi), %rcx +; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: js .LBB83_7 +; SSE2-NEXT: # %bb.8: +; SSE2-NEXT: cvtsi2ss %rcx, %xmm2 +; SSE2-NEXT: jmp .LBB83_9 +; SSE2-NEXT: .LBB83_7: ; SSE2-NEXT: movq %rcx, %rdx ; SSE2-NEXT: shrq %rdx ; SSE2-NEXT: andl $1, %ecx ; SSE2-NEXT: orq %rdx, %rcx ; SSE2-NEXT: cvtsi2ss %rcx, %xmm2 ; SSE2-NEXT: addss %xmm2, %xmm2 -; SSE2-NEXT: .LBB83_6: -; SSE2-NEXT: movdqa (%rdi), %xmm3 -; SSE2-NEXT: testq %rax, %rax -; SSE2-NEXT: js .LBB83_7 -; SSE2-NEXT: # %bb.8: -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: jmp .LBB83_9 -; SSE2-NEXT: .LBB83_7: -; SSE2-NEXT: movq %rax, %rcx -; SSE2-NEXT: shrq %rcx -; SSE2-NEXT: andl $1, %eax -; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: addss %xmm0, %xmm0 ; SSE2-NEXT: .LBB83_9: -; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm3[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB83_10 ; SSE2-NEXT: # %bb.11: -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 +; SSE2-NEXT: xorps %xmm0, %xmm0 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: jmp .LBB83_12 ; SSE2-NEXT: .LBB83_10: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 -; SSE2-NEXT: addss %xmm2, %xmm2 +; SSE2-NEXT: xorps %xmm0, %xmm0 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 +; SSE2-NEXT: addss %xmm0, %xmm0 ; SSE2-NEXT: .LBB83_12: ; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] ; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] @@ -4591,8 +4532,7 @@ define <4 x float> @uitofp_load_4i8_to_4f32(ptr%a) { define <8 x float> @uitofp_load_8i64_to_8f32(ptr%a) { ; SSE2-LABEL: uitofp_load_8i64_to_8f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: movq 24(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_1 ; SSE2-NEXT: # %bb.2: @@ -4606,127 +4546,114 @@ define <8 x float> @uitofp_load_8i64_to_8f32(ptr%a) { ; SSE2-NEXT: cvtsi2ss %rax, %xmm2 ; SSE2-NEXT: addss %xmm2, %xmm2 ; SSE2-NEXT: .LBB87_3: -; SSE2-NEXT: movq (%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rcx -; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_4 ; SSE2-NEXT: # %bb.5: -; SSE2-NEXT: cvtsi2ss %rcx, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: jmp .LBB87_6 ; SSE2-NEXT: .LBB87_4: -; SSE2-NEXT: movq %rcx, %rdx -; SSE2-NEXT: shrq %rdx -; SSE2-NEXT: andl $1, %ecx -; SSE2-NEXT: orq %rdx, %rcx -; SSE2-NEXT: cvtsi2ss %rcx, %xmm1 +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: shrq %rcx +; SSE2-NEXT: andl $1, %eax +; SSE2-NEXT: orq %rcx, %rax +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: addss %xmm1, %xmm1 ; SSE2-NEXT: .LBB87_6: -; SSE2-NEXT: movdqa (%rdi), %xmm3 -; SSE2-NEXT: testq %rax, %rax +; SSE2-NEXT: movq (%rdi), %rax +; SSE2-NEXT: movq 8(%rdi), %rcx +; SSE2-NEXT: testq %rcx, %rcx ; SSE2-NEXT: js .LBB87_7 ; SSE2-NEXT: # %bb.8: -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: jmp .LBB87_9 -; SSE2-NEXT: .LBB87_7: +; SSE2-NEXT: cvtsi2ss %rcx, %xmm3 +; SSE2-NEXT: testq %rax, %rax +; SSE2-NEXT: jns .LBB87_11 +; SSE2-NEXT: .LBB87_10: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 ; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: addss %xmm0, %xmm0 -; SSE2-NEXT: .LBB87_9: -; SSE2-NEXT: movq 48(%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] -; SSE2-NEXT: movq %xmm3, %rcx -; SSE2-NEXT: testq %rcx, %rcx -; SSE2-NEXT: js .LBB87_10 -; SSE2-NEXT: # %bb.11: -; SSE2-NEXT: cvtsi2ss %rcx, %xmm4 ; SSE2-NEXT: jmp .LBB87_12 -; SSE2-NEXT: .LBB87_10: +; SSE2-NEXT: .LBB87_7: ; SSE2-NEXT: movq %rcx, %rdx ; SSE2-NEXT: shrq %rdx ; SSE2-NEXT: andl $1, %ecx ; SSE2-NEXT: orq %rdx, %rcx -; SSE2-NEXT: cvtsi2ss %rcx, %xmm4 -; SSE2-NEXT: addss %xmm4, %xmm4 +; SSE2-NEXT: cvtsi2ss %rcx, %xmm3 +; SSE2-NEXT: addss %xmm3, %xmm3 +; SSE2-NEXT: testq %rax, %rax +; SSE2-NEXT: js .LBB87_10 +; SSE2-NEXT: .LBB87_11: +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: .LBB87_12: -; SSE2-NEXT: movdqa 48(%rdi), %xmm5 +; SSE2-NEXT: movq 56(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_13 ; SSE2-NEXT: # %bb.14: -; SSE2-NEXT: xorps %xmm3, %xmm3 -; SSE2-NEXT: cvtsi2ss %rax, %xmm3 +; SSE2-NEXT: cvtsi2ss %rax, %xmm5 ; SSE2-NEXT: jmp .LBB87_15 ; SSE2-NEXT: .LBB87_13: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm3, %xmm3 -; SSE2-NEXT: cvtsi2ss %rax, %xmm3 -; SSE2-NEXT: addss %xmm3, %xmm3 +; SSE2-NEXT: cvtsi2ss %rax, %xmm5 +; SSE2-NEXT: addss %xmm5, %xmm5 ; SSE2-NEXT: .LBB87_15: -; SSE2-NEXT: movq 32(%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm5[2,3,2,3] -; SSE2-NEXT: movq %xmm5, %rcx -; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: movq 48(%rdi), %rax +; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_16 ; SSE2-NEXT: # %bb.17: -; SSE2-NEXT: xorps %xmm5, %xmm5 -; SSE2-NEXT: cvtsi2ss %rcx, %xmm5 +; SSE2-NEXT: cvtsi2ss %rax, %xmm4 ; SSE2-NEXT: jmp .LBB87_18 ; SSE2-NEXT: .LBB87_16: -; SSE2-NEXT: movq %rcx, %rdx -; SSE2-NEXT: shrq %rdx -; SSE2-NEXT: andl $1, %ecx -; SSE2-NEXT: orq %rdx, %rcx -; SSE2-NEXT: xorps %xmm5, %xmm5 -; SSE2-NEXT: cvtsi2ss %rcx, %xmm5 -; SSE2-NEXT: addss %xmm5, %xmm5 +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: shrq %rcx +; SSE2-NEXT: andl $1, %eax +; SSE2-NEXT: orq %rcx, %rax +; SSE2-NEXT: cvtsi2ss %rax, %xmm4 +; SSE2-NEXT: addss %xmm4, %xmm4 ; SSE2-NEXT: .LBB87_18: -; SSE2-NEXT: unpcklps {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1] -; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1] -; SSE2-NEXT: movdqa 32(%rdi), %xmm4 +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] +; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] +; SSE2-NEXT: movq 40(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_19 ; SSE2-NEXT: # %bb.20: -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: xorps %xmm2, %xmm2 +; SSE2-NEXT: cvtsi2ss %rax, %xmm2 ; SSE2-NEXT: jmp .LBB87_21 ; SSE2-NEXT: .LBB87_19: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: addss %xmm1, %xmm1 +; SSE2-NEXT: xorps %xmm2, %xmm2 +; SSE2-NEXT: cvtsi2ss %rax, %xmm2 +; SSE2-NEXT: addss %xmm2, %xmm2 ; SSE2-NEXT: .LBB87_21: -; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm2[0] -; SSE2-NEXT: unpcklps {{.*#+}} xmm3 = xmm3[0],xmm5[0],xmm3[1],xmm5[1] -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm4[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: unpcklps {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1] +; SSE2-NEXT: movq 32(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_22 ; SSE2-NEXT: # %bb.23: -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 +; SSE2-NEXT: xorps %xmm1, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: jmp .LBB87_24 ; SSE2-NEXT: .LBB87_22: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 -; SSE2-NEXT: addss %xmm2, %xmm2 +; SSE2-NEXT: xorps %xmm1, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: addss %xmm1, %xmm1 ; SSE2-NEXT: .LBB87_24: ; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm4[0] ; SSE2-NEXT: retq ; ; SSE41-LABEL: uitofp_load_8i64_to_8f32: -- GitLab From 5d3ef06509c2f1fc5384fa64e5848d12f7b8811e Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 27 Mar 2024 17:15:48 +0000 Subject: [PATCH 088/541] [X86] combine-pavg.ll - add demandedelts test coverage for #86284 --- llvm/test/CodeGen/X86/combine-pavg.ll | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/llvm/test/CodeGen/X86/combine-pavg.ll b/llvm/test/CodeGen/X86/combine-pavg.ll index 9bb7fec7eeac..7a8ddf5178d3 100644 --- a/llvm/test/CodeGen/X86/combine-pavg.ll +++ b/llvm/test/CodeGen/X86/combine-pavg.ll @@ -80,3 +80,33 @@ define <16 x i8> @combine_pavgw_knownbits(<8 x i16> %a0, <8 x i16> %a1, <8 x i16 %trunc = trunc <16 x i16> %shuffle to <16 x i8> ret <16 x i8> %trunc } + +define <8 x i16> @combine_pavgw_demandedelts(<8 x i16> %a0, <8 x i16> %a1) { +; SSE-LABEL: combine_pavgw_demandedelts: +; SSE: # %bb.0: +; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,0,0,0,4,5,6,7] +; SSE-NEXT: pshufb {{.*#+}} xmm0 = xmm0[0,1,0,1,0,1,0,1,8,9,8,9,12,13,12,13] +; SSE-NEXT: pavgw %xmm1, %xmm0 +; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,0,0,0] +; SSE-NEXT: retq +; +; AVX1-LABEL: combine_pavgw_demandedelts: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshuflw {{.*#+}} xmm1 = xmm1[0,0,0,0,4,5,6,7] +; AVX1-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,1,0,1,0,1,0,1,8,9,8,9,12,13,12,13] +; AVX1-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,0,0,0] +; AVX1-NEXT: retq +; +; AVX2-LABEL: combine_pavgw_demandedelts: +; AVX2: # %bb.0: +; AVX2-NEXT: vpbroadcastw %xmm1, %xmm1 +; AVX2-NEXT: vpbroadcastw %xmm0, %xmm0 +; AVX2-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq + %s0 = shufflevector <8 x i16> %a0, <8 x i16> poison, <8 x i32> + %avg = tail call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %s0, <8 x i16> %a1) + %shuffle = shufflevector <8 x i16> %avg, <8 x i16> poison, <8 x i32> zeroinitializer + ret <8 x i16> %shuffle +} + -- GitLab From 35d55f2894a2a2cdca5db494f519aa5ec7273678 Mon Sep 17 00:00:00 2001 From: Justin Fargnoli Date: Wed, 27 Mar 2024 10:30:17 -0700 Subject: [PATCH 089/541] [NFC][mlir] Reorder `declarePromisedInterface()` operands (#86628) Reorder the template operands of `declarePromisedInterface()` to match `declarePromisedInterfaces()`. --- mlir/include/mlir/IR/Dialect.h | 4 ++-- mlir/lib/Dialect/Arith/IR/ArithDialect.cpp | 6 +++--- mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp | 2 +- mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp | 6 +++--- mlir/lib/Dialect/Func/IR/FuncOps.cpp | 4 ++-- mlir/lib/Dialect/GPU/IR/GPUDialect.cpp | 4 ++-- mlir/lib/Dialect/Index/IR/IndexDialect.cpp | 2 +- mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp | 4 ++-- mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp | 2 +- mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp | 12 ++++++------ mlir/lib/Dialect/Math/IR/MathDialect.cpp | 2 +- mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp | 4 ++-- mlir/lib/Dialect/SCF/IR/SCF.cpp | 2 +- mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp | 2 +- mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp | 2 +- mlir/lib/Dialect/UB/IR/UBOps.cpp | 2 +- mlir/lib/Dialect/Vector/IR/VectorOps.cpp | 4 ++-- mlir/unittests/IR/InterfaceAttachmentTest.cpp | 4 ++-- 18 files changed, 34 insertions(+), 34 deletions(-) diff --git a/mlir/include/mlir/IR/Dialect.h b/mlir/include/mlir/IR/Dialect.h index 6c8a170a03c7..f7c1f4df16fc 100644 --- a/mlir/include/mlir/IR/Dialect.h +++ b/mlir/include/mlir/IR/Dialect.h @@ -210,7 +210,7 @@ public: /// registration. The promised interface type can be an interface of any type /// not just a dialect interface, i.e. it may also be an /// AttributeInterface/OpInterface/TypeInterface/etc. - template + template void declarePromisedInterface() { unresolvedPromisedInterfaces.insert( {TypeID::get(), InterfaceT::getInterfaceID()}); @@ -221,7 +221,7 @@ public: // declarePromisedInterfaces() template void declarePromisedInterfaces() { - (declarePromisedInterface(), ...); + (declarePromisedInterface(), ...); } /// Checks if the given interface, which is attempting to be used, is a diff --git a/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp b/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp index 6a593185cced..042acf610090 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp +++ b/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp @@ -48,9 +48,9 @@ void arith::ArithDialect::initialize() { #include "mlir/Dialect/Arith/IR/ArithOpsAttributes.cpp.inc" >(); addInterfaces(); - declarePromisedInterface(); - declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); declarePromisedInterfaces(); declarePromisedInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); addInterfaces(); } diff --git a/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp index c6b02b9703e7..5d11f8f6cc45 100644 --- a/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp +++ b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp @@ -70,11 +70,11 @@ void ControlFlowDialect::initialize() { #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.cpp.inc" >(); addInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); declarePromisedInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/Func/IR/FuncOps.cpp b/mlir/lib/Dialect/Func/IR/FuncOps.cpp index ed2ecfe9d0fb..95589e8989e2 100644 --- a/mlir/lib/Dialect/Func/IR/FuncOps.cpp +++ b/mlir/lib/Dialect/Func/IR/FuncOps.cpp @@ -42,8 +42,8 @@ void FuncDialect::initialize() { #define GET_OP_LIST #include "mlir/Dialect/Func/IR/FuncOps.cpp.inc" >(); - declarePromisedInterface(); - declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); declarePromisedInterfaces(); } diff --git a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp index a02eca8b1179..f1b9ca5c5002 100644 --- a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp +++ b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp @@ -216,8 +216,8 @@ void GPUDialect::initialize() { #include "mlir/Dialect/GPU/IR/GPUOpsAttributes.cpp.inc" >(); addInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); } static std::string getSparseHandleKeyword(SparseHandleKind kind) { diff --git a/mlir/lib/Dialect/Index/IR/IndexDialect.cpp b/mlir/lib/Dialect/Index/IR/IndexDialect.cpp index d631afa63b9a..183d0e33b252 100644 --- a/mlir/lib/Dialect/Index/IR/IndexDialect.cpp +++ b/mlir/lib/Dialect/Index/IR/IndexDialect.cpp @@ -19,7 +19,7 @@ using namespace mlir::index; void IndexDialect::initialize() { registerAttributes(); registerOperations(); - declarePromisedInterface(); + declarePromisedInterface(); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp index 9e8407451a08..94197e473ce0 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp @@ -1044,8 +1044,8 @@ void NVVMDialect::initialize() { // Support unknown operations because not all NVVM operations are // registered. allowUnknownOperations(); - declarePromisedInterface(); - declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); } LogicalResult NVVMDialect::verifyOperationAttribute(Operation *op, diff --git a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp index 0f2e75cd7e8b..65b770ae3261 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp @@ -247,7 +247,7 @@ void ROCDLDialect::initialize() { // Support unknown operations because not all ROCDL operations are registered. allowUnknownOperations(); - declarePromisedInterface(); + declarePromisedInterface(); } LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op, diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp index a6936fde4370..9e50c355c504 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp @@ -123,16 +123,16 @@ void mlir::linalg::LinalgDialect::initialize() { addInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); declarePromisedInterfaces(); - declarePromisedInterface(); - declarePromisedInterface(); - declarePromisedInterface(); - declarePromisedInterface(); - declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); declarePromisedInterfaces(); addInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); } diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp index 41082a85a485..3a8bd12ba258 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp @@ -47,14 +47,14 @@ void mlir::memref::MemRefDialect::initialize() { #include "mlir/Dialect/MemRef/IR/MemRefOps.cpp.inc" >(); addInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); declarePromisedInterfaces(); declarePromisedInterfaces(); declarePromisedInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); } /// Finds the unique dealloc operation (if one exists) for `allocValue`. diff --git a/mlir/lib/Dialect/SCF/IR/SCF.cpp b/mlir/lib/Dialect/SCF/IR/SCF.cpp index ddb9676eb4f6..5bca8e85f889 100644 --- a/mlir/lib/Dialect/SCF/IR/SCF.cpp +++ b/mlir/lib/Dialect/SCF/IR/SCF.cpp @@ -79,7 +79,7 @@ void SCFDialect::initialize() { declarePromisedInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); } /// Default callback for IfOp builders. Inserts a yield without arguments. diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp index e914f46bdef6..72488d6e5d0b 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp @@ -135,7 +135,7 @@ void SPIRVDialect::initialize() { // Allow unknown operations because SPIR-V is extensible. allowUnknownOperations(); - declarePromisedInterface(); + declarePromisedInterface(); } std::string SPIRVDialect::getAttributeName(Decoration decoration) { diff --git a/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp b/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp index 4b3156728cc9..002077753b13 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp @@ -62,7 +62,7 @@ void TensorDialect::initialize() { ParallelInsertSliceOp>(); declarePromisedInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); declarePromisedInterfaces(); declarePromisedInterfaces(); diff --git a/mlir/lib/Dialect/UB/IR/UBOps.cpp b/mlir/lib/Dialect/UB/IR/UBOps.cpp index 3a2010cdcb5c..5b2cfe7bf426 100644 --- a/mlir/lib/Dialect/UB/IR/UBOps.cpp +++ b/mlir/lib/Dialect/UB/IR/UBOps.cpp @@ -46,7 +46,7 @@ void UBDialect::initialize() { #include "mlir/Dialect/UB/IR/UBOpsAttributes.cpp.inc" >(); addInterfaces(); - declarePromisedInterface(); + declarePromisedInterface(); } Operation *UBDialect::materializeConstant(OpBuilder &builder, Attribute value, diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp index 35296824246e..e566bfacf379 100644 --- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp +++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp @@ -382,8 +382,8 @@ void VectorDialect::initialize() { YieldOp>(); declarePromisedInterfaces(); - declarePromisedInterface(); - declarePromisedInterface(); + declarePromisedInterface(); + declarePromisedInterface(); } /// Materialize a single constant operation from a given attribute value with diff --git a/mlir/unittests/IR/InterfaceAttachmentTest.cpp b/mlir/unittests/IR/InterfaceAttachmentTest.cpp index 16de34c45ec6..58049a9969e3 100644 --- a/mlir/unittests/IR/InterfaceAttachmentTest.cpp +++ b/mlir/unittests/IR/InterfaceAttachmentTest.cpp @@ -431,8 +431,8 @@ TEST(InterfaceAttachmentTest, PromisedInterfaces) { attr.hasPromiseOrImplementsInterface()); // Add a promise `TestExternalAttrInterface`. - testDialect->declarePromisedInterface(); + testDialect->declarePromisedInterface(); EXPECT_TRUE( attr.hasPromiseOrImplementsInterface()); -- GitLab From 96b3969a4d9e8faa3dd9b7e8b2696e2684cdebef Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 10:30:58 -0700 Subject: [PATCH 090/541] [NFC][HWASAN] Precommit globals-access test HWASAN does not behave as expected yet. Reviewers: fmayer, thurstond Reviewed By: fmayer, thurstond Pull Request: https://github.com/llvm/llvm-project/pull/86771 --- .../HWAddressSanitizer/globals-access.ll | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll new file mode 100644 index 000000000000..c83911f60149 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll @@ -0,0 +1,60 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --global-value-regex "x" --version 4 +; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64 -hwasan-globals=0 | FileCheck %s --check-prefixes=NOGLOB +; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64 -hwasan-globals=1 | FileCheck %s + +@x = dso_local global i32 0, align 4 + +;. +; NOGLOB: @x = dso_local global i32 0, align 4 +;. +; CHECK: @x = alias i32, inttoptr (i64 add (i64 ptrtoint (ptr @x.hwasan to i64), i64 5260204364768739328) to ptr) +;. +define dso_local noundef i32 @_Z3tmpv() sanitize_hwaddress { +; NOGLOB-LABEL: define dso_local noundef i32 @_Z3tmpv( +; NOGLOB-SAME: ) #[[ATTR0:[0-9]+]] { +; NOGLOB-NEXT: entry: +; NOGLOB-NEXT: [[TMP12:%.*]] = load i64, ptr @__hwasan_tls, align 8 +; NOGLOB-NEXT: [[TMP1:%.*]] = or i64 [[TMP12]], 4294967295 +; NOGLOB-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP1]], 1 +; NOGLOB-NEXT: [[TMP2:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr +; NOGLOB-NEXT: [[TMP3:%.*]] = lshr i64 ptrtoint (ptr @x to i64), 56 +; NOGLOB-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i8 +; NOGLOB-NEXT: [[TMP5:%.*]] = and i64 ptrtoint (ptr @x to i64), 72057594037927935 +; NOGLOB-NEXT: [[TMP6:%.*]] = lshr i64 [[TMP5]], 4 +; NOGLOB-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP2]], i64 [[TMP6]] +; NOGLOB-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1 +; NOGLOB-NEXT: [[TMP9:%.*]] = icmp ne i8 [[TMP4]], [[TMP8]] +; NOGLOB-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP11:%.*]], !prof [[PROF1:![0-9]+]] +; NOGLOB: 10: +; NOGLOB-NEXT: call void @llvm.hwasan.check.memaccess.shortgranules(ptr [[TMP2]], ptr @x, i32 2) +; NOGLOB-NEXT: br label [[TMP11]] +; NOGLOB: 11: +; NOGLOB-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 +; NOGLOB-NEXT: ret i32 [[TMP0]] +; +; CHECK-LABEL: define dso_local noundef i32 @_Z3tmpv( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__hwasan_tls, align 8 +; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[TMP12]], 4294967295 +; CHECK-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP1]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr +; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 ptrtoint (ptr @x to i64), 56 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i8 +; CHECK-NEXT: [[TMP5:%.*]] = and i64 ptrtoint (ptr @x to i64), 72057594037927935 +; CHECK-NEXT: [[TMP6:%.*]] = lshr i64 [[TMP5]], 4 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP2]], i64 [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1 +; CHECK-NEXT: [[TMP9:%.*]] = icmp ne i8 [[TMP4]], [[TMP8]] +; CHECK-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP11:%.*]], !prof [[PROF2:![0-9]+]] +; CHECK: 10: +; CHECK-NEXT: call void @llvm.hwasan.check.memaccess.shortgranules(ptr [[TMP2]], ptr @x, i32 2) +; CHECK-NEXT: br label [[TMP11]] +; CHECK: 11: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 +; CHECK-NEXT: ret i32 [[TMP0]] +; +entry: + %0 = load i32, ptr @x, align 4 + ret i32 %0 +} -- GitLab From e96f652bd02b6b8e11c390564267ec7634ab6205 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 10:35:37 -0700 Subject: [PATCH 091/541] [NFC][IR] Add SetNoSanitize helpers (#86772) This will be used by #86775 --- llvm/include/llvm/IR/GlobalValue.h | 1 + llvm/include/llvm/IR/IRBuilder.h | 6 ++++++ llvm/lib/IR/Globals.cpp | 7 +++++++ 3 files changed, 14 insertions(+) diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h index aa8188cd99fe..c61d502aa332 100644 --- a/llvm/include/llvm/IR/GlobalValue.h +++ b/llvm/include/llvm/IR/GlobalValue.h @@ -360,6 +360,7 @@ public: // storage is shared between `G1` and `G2`. void setSanitizerMetadata(SanitizerMetadata Meta); void removeSanitizerMetadata(); + void setNoSanitizeMetadata(); bool isTagged() const { return hasSanitizerMetadata() && getSanitizerMetadata().Memtag; diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index a6165ef13fd7..2a0c1e9e8c44 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -221,6 +221,12 @@ public: AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); } + /// Set nosanitize metadata. + void SetNoSanitizeMetadata() { + AddOrRemoveMetadataToCopy(llvm::LLVMContext::MD_nosanitize, + llvm::MDNode::get(getContext(), std::nullopt)); + } + /// Collect metadata with IDs \p MetadataKinds from \p Src which should be /// added to all created instructions. Entries present in MedataDataToCopy but /// not on \p Src will be dropped from MetadataToCopy. diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index 481a1d802e66..40f854a2c906 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -243,6 +243,13 @@ void GlobalValue::removeSanitizerMetadata() { HasSanitizerMetadata = false; } +void GlobalValue::setNoSanitizeMetadata() { + SanitizerMetadata Meta; + Meta.NoAddress = true; + Meta.NoHWAddress = true; + setSanitizerMetadata(Meta); +} + StringRef GlobalObject::getSectionImpl() const { assert(hasSection()); return getContext().pImpl->GlobalObjectSections[this]; -- GitLab From 5a7341a7ae29be80be944b73419eba4017826cd1 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Wed, 27 Mar 2024 18:53:47 +0100 Subject: [PATCH 092/541] [NFC][libc++][TZDB] Improves some internals. (#84800) Removes some unneeded overloads in the pimpl class; they implementation could be in the caller. The pimpl member functions are __uglified. --- libcxx/include/__chrono/tzdb_list.h | 22 +++++++++++++------ libcxx/src/include/tzdb/tzdb_list_private.h | 11 ++++------ libcxx/src/tzdb_list.cpp | 24 ++++++++++----------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/libcxx/include/__chrono/tzdb_list.h b/libcxx/include/__chrono/tzdb_list.h index 112e04ff2ee6..e8aaf31e3631 100644 --- a/libcxx/include/__chrono/tzdb_list.h +++ b/libcxx/include/__chrono/tzdb_list.h @@ -52,19 +52,29 @@ public: using const_iterator = forward_list::const_iterator; - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const tzdb& front() const noexcept; + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } - _LIBCPP_EXPORTED_FROM_ABI const_iterator erase_after(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI const_iterator erase_after(const_iterator __p) { return __erase_after(__p); } - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator begin() const noexcept; - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator end() const noexcept; + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __begin(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __end(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator cbegin() const noexcept; - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator cend() const noexcept; + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return __cbegin(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return __cend(); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __impl& __implementation() { return *__impl_; } private: + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const tzdb& __front() const noexcept; + + _LIBCPP_EXPORTED_FROM_ABI const_iterator __erase_after(const_iterator __p); + + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __begin() const noexcept; + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __end() const noexcept; + + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __cbegin() const noexcept; + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __cend() const noexcept; + __impl* __impl_; }; diff --git a/libcxx/src/include/tzdb/tzdb_list_private.h b/libcxx/src/include/tzdb/tzdb_list_private.h index f43d7d8ea772..969b2b9f8a9f 100644 --- a/libcxx/src/include/tzdb/tzdb_list_private.h +++ b/libcxx/src/include/tzdb/tzdb_list_private.h @@ -54,14 +54,14 @@ public: using const_iterator = tzdb_list::const_iterator; - const tzdb& front() const noexcept { + const tzdb& __front() const noexcept { #ifndef _LIBCPP_HAS_NO_THREADS shared_lock __lock{__mutex_}; #endif return __tzdb_.front(); } - const_iterator erase_after(const_iterator __p) { + const_iterator __erase_after(const_iterator __p) { #ifndef _LIBCPP_HAS_NO_THREADS unique_lock __lock{__mutex_}; #endif @@ -70,20 +70,17 @@ public: return __tzdb_.erase_after(__p); } - const_iterator begin() const noexcept { + const_iterator __begin() const noexcept { #ifndef _LIBCPP_HAS_NO_THREADS shared_lock __lock{__mutex_}; #endif return __tzdb_.begin(); } - const_iterator end() const noexcept { + const_iterator __end() const noexcept { // forward_list::end does not access the list, so no need to take a lock. return __tzdb_.end(); } - const_iterator cbegin() const noexcept { return begin(); } - const_iterator cend() const noexcept { return end(); } - private: // Loads the tzdbs // pre: The caller ensures the locking, if needed, is done. diff --git a/libcxx/src/tzdb_list.cpp b/libcxx/src/tzdb_list.cpp index d3ee8b58f98b..b99c30a9b9e6 100644 --- a/libcxx/src/tzdb_list.cpp +++ b/libcxx/src/tzdb_list.cpp @@ -18,26 +18,24 @@ namespace chrono { _LIBCPP_EXPORTED_FROM_ABI tzdb_list::~tzdb_list() { delete __impl_; } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const tzdb& tzdb_list::front() const noexcept { - return __impl_->front(); -} +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const tzdb& tzdb_list::__front() const noexcept { return __impl_->__front(); } -_LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::erase_after(const_iterator __p) { - return __impl_->erase_after(__p); +_LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__erase_after(const_iterator __p) { + return __impl_->__erase_after(__p); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::begin() const noexcept { - return __impl_->begin(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__begin() const noexcept { + return __impl_->__begin(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::end() const noexcept { - return __impl_->end(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__end() const noexcept { + return __impl_->__end(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::cbegin() const noexcept { - return __impl_->cbegin(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__cbegin() const noexcept { + return __impl_->__begin(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::cend() const noexcept { - return __impl_->cend(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__cend() const noexcept { + return __impl_->__end(); } } // namespace chrono -- GitLab From 52431fdb1ab8d29be078edd55250e06381e4b6b0 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Wed, 27 Mar 2024 11:11:16 -0700 Subject: [PATCH 093/541] [WebAssembly] Remove threwValue comparison after __wasm_setjmp_test (#86633) Currently the code thinks a `longjmp` occurred if both `__THREW__` and `__threwValue` are nonzero. But `__threwValue` can be 0, and the `longjmp` library function should change it to 1 in case it is 0: https://en.cppreference.com/w/c/program/longjmp Emscripten libraries were not consistent about that, but after https://github.com/emscripten-core/emscripten/pull/21493 and https://github.com/emscripten-core/emscripten/pull/21502, we correctly pass 1 in case the input is 0. So there will be no case `__threwValue` is 0. And regardless of what `longjmp` library function does, treating `longjmp`'s 0 input to its second argument as "not longjmping" doesn't seem right. I'm not sure where that `__threwValue` checking came from, but probably I was porting then fastcomp's implementation and moved this part just verbatim: https://github.com/emscripten-core/emscripten-fastcomp/blob/9bdc7bb4fc595fe05a021b06fe350e8494a741a1/lib/Target/JSBackend/CallHandlers.h#L274-L278 Just for the context, how this was discovered: https://github.com/emscripten-core/emscripten/pull/21502#pullrequestreview-1942160300 --- .../WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp | 8 +++----- llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll | 7 +++---- llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll | 4 +--- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp index 027ee1086bf4..0788d0c3a721 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -153,7 +153,7 @@ /// %__THREW__.val = __THREW__; /// __THREW__ = 0; /// %__threwValue.val = __threwValue; -/// if (%__THREW__.val != 0 & %__threwValue.val != 0) { +/// if (%__THREW__.val != 0) { /// %label = __wasm_setjmp_test(%__THREW__.val, functionInvocationId); /// if (%label == 0) /// emscripten_longjmp(%__THREW__.val, %__threwValue.val); @@ -712,12 +712,10 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp( BasicBlock *ThenBB1 = BasicBlock::Create(C, "if.then1", F); BasicBlock *ElseBB1 = BasicBlock::Create(C, "if.else1", F); BasicBlock *EndBB1 = BasicBlock::Create(C, "if.end", F); - Value *ThrewCmp = IRB.CreateICmpNE(Threw, getAddrSizeInt(M, 0)); Value *ThrewValue = IRB.CreateLoad(IRB.getInt32Ty(), ThrewValueGV, ThrewValueGV->getName() + ".val"); - Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0)); - Value *Cmp1 = IRB.CreateAnd(ThrewCmp, ThrewValueCmp, "cmp1"); - IRB.CreateCondBr(Cmp1, ThenBB1, ElseBB1); + Value *ThrewCmp = IRB.CreateICmpNE(Threw, getAddrSizeInt(M, 0)); + IRB.CreateCondBr(ThrewCmp, ThenBB1, ElseBB1); // Generate call.em.longjmp BB once and share it within the function if (!CallEmLongjmpBB) { diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll index 32942cd92e68..d88f42a4dc58 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll @@ -22,10 +22,8 @@ entry: to label %try.cont unwind label %lpad ; CHECK: entry.split.split: -; CHECK: %[[CMP0:.*]] = icmp ne i32 %__THREW__.val, 0 -; CHECK-NEXT: %__threwValue.val = load i32, ptr @__threwValue -; CHECK-NEXT: %[[CMP1:.*]] = icmp ne i32 %__threwValue.val, 0 -; CHECK-NEXT: %[[CMP:.*]] = and i1 %[[CMP0]], %[[CMP1]] +; CHECK: %__threwValue.val = load i32, ptr @__threwValue +; CHECK-NEXT: %[[CMP:.*]] = icmp ne i32 %__THREW__.val, 0 ; CHECK-NEXT: br i1 %[[CMP]], label %if.then1, label %if.else1 ; This is exception checking part. %if.else1 leads here @@ -121,6 +119,7 @@ if.end: ; preds = %entry ; CHECK-NEXT: unreachable ; CHECK: normal: +; CHECK-NEXT: %__threwValue.val = load i32, ptr @__threwValue, align 4 ; CHECK-NEXT: icmp ne i32 %__THREW__.val, 0 return: ; preds = %if.end, %entry diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll index 27ec95a2c462..dca4c59d7c87 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll @@ -37,10 +37,8 @@ entry: ; CHECK-NEXT: call cc{{.*}} void @__invoke_void_[[PTR]]_i32(ptr @emscripten_longjmp, [[PTR]] %[[JMPBUF]], i32 1) ; CHECK-NEXT: %[[__THREW__VAL:.*]] = load [[PTR]], ptr @__THREW__ ; CHECK-NEXT: store [[PTR]] 0, ptr @__THREW__ -; CHECK-NEXT: %[[CMP0:.*]] = icmp ne [[PTR]] %__THREW__.val, 0 ; CHECK-NEXT: %[[THREWVALUE_VAL:.*]] = load i32, ptr @__threwValue -; CHECK-NEXT: %[[CMP1:.*]] = icmp ne i32 %[[THREWVALUE_VAL]], 0 -; CHECK-NEXT: %[[CMP:.*]] = and i1 %[[CMP0]], %[[CMP1]] +; CHECK-NEXT: %[[CMP:.*]] = icmp ne [[PTR]] %__THREW__.val, 0 ; CHECK-NEXT: br i1 %[[CMP]], label %if.then1, label %if.else1 ; CHECK: entry.split.split.split: -- GitLab From 2598aa67c8fa733455af1b9738f257653ee6322b Mon Sep 17 00:00:00 2001 From: Lei Wang Date: Wed, 27 Mar 2024 11:14:21 -0700 Subject: [PATCH 094/541] [CSSPGO] Reject high checksum mismatched profile (#84097) Error out the build if the checksum mismatch is extremely high, it's better to drop the profile rather than apply the bad profile. Note that the check is on a module level, the user could make big changes to functions in one single module but those changes might not be performance significant to the whole binary, so we want to be conservative, only expect to catch big perf regression. To do this, we select a set of the "hot" functions for the check. We use two parameter(`hot-func-cutoff-for-staleness-error` and `min-functions-for-staleness-error`) to control the function selection to make sure the selected are hot enough and the num of function is not small. Tuned the parameters on our internal services, it works to catch big perf regression due to the high mismatch . --- llvm/lib/Transforms/IPO/SampleProfile.cpp | 71 +++++++++++++++++++ .../pseudo-probe-profile-mismatch-error.ll | 7 ++ 2 files changed, 78 insertions(+) create mode 100644 llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch-error.ll diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index 9a8040bc4b06..2cbef8a7ae61 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -234,6 +234,21 @@ static cl::opt ProfileICPRelativeHotnessSkip( cl::desc( "Skip relative hotness check for ICP up to given number of targets.")); +static cl::opt HotFuncCutoffForStalenessError( + "hot-func-cutoff-for-staleness-error", cl::Hidden, cl::init(800000), + cl::desc("A function is considered hot for staleness error check if its " + "total sample count is above the specified percentile")); + +static cl::opt MinfuncsForStalenessError( + "min-functions-for-staleness-error", cl::Hidden, cl::init(50), + cl::desc("Skip the check if the number of hot functions is smaller than " + "the specified number.")); + +static cl::opt PrecentMismatchForStalenessError( + "precent-mismatch-for-staleness-error", cl::Hidden, cl::init(80), + cl::desc("Reject the profile if the mismatch percent is higher than the " + "given number.")); + static cl::opt CallsitePrioritizedInline( "sample-profile-prioritized-inline", cl::Hidden, @@ -630,6 +645,8 @@ protected: std::vector buildFunctionOrder(Module &M, LazyCallGraph &CG); std::unique_ptr buildProfiledCallGraph(Module &M); void generateMDProfMetadata(Function &F); + bool rejectHighStalenessProfile(Module &M, ProfileSummaryInfo *PSI, + const SampleProfileMap &Profiles); /// Map from function name to Function *. Used to find the function from /// the function name. If the function name contains suffix, additional @@ -2187,6 +2204,55 @@ bool SampleProfileLoader::doInitialization(Module &M, return true; } +// Note that this is a module-level check. Even if one module is errored out, +// the entire build will be errored out. However, the user could make big +// changes to functions in single module but those changes might not be +// performance significant to the whole binary. Therefore, to avoid those false +// positives, we select a reasonable big set of hot functions that are supposed +// to be globally performance significant, only compute and check the mismatch +// within those functions. The function selection is based on two criteria: +// 1) The function is hot enough, which is tuned by a hotness-based +// flag(HotFuncCutoffForStalenessError). 2) The num of function is large enough +// which is tuned by the MinfuncsForStalenessError flag. +bool SampleProfileLoader::rejectHighStalenessProfile( + Module &M, ProfileSummaryInfo *PSI, const SampleProfileMap &Profiles) { + assert(FunctionSamples::ProfileIsProbeBased && + "Only support for probe-based profile"); + uint64_t TotalHotFunc = 0; + uint64_t NumMismatchedFunc = 0; + for (const auto &I : Profiles) { + const auto &FS = I.second; + const auto *FuncDesc = ProbeManager->getDesc(FS.getGUID()); + if (!FuncDesc) + continue; + + // Use a hotness-based threshold to control the function selection. + if (!PSI->isHotCountNthPercentile(HotFuncCutoffForStalenessError, + FS.getTotalSamples())) + continue; + + TotalHotFunc++; + if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) + NumMismatchedFunc++; + } + // Make sure that the num of selected function is not too small to distinguish + // from the user's benign changes. + if (TotalHotFunc < MinfuncsForStalenessError) + return false; + + // Finally check the mismatch percentage against the threshold. + if (NumMismatchedFunc * 100 >= + TotalHotFunc * PrecentMismatchForStalenessError) { + auto &Ctx = M.getContext(); + const char *Msg = + "The input profile significantly mismatches current source code. " + "Please recollect profile to avoid performance regression."; + Ctx.diagnose(DiagnosticInfoSampleProfile(M.getModuleIdentifier(), Msg)); + return true; + } + return false; +} + void SampleProfileMatcher::findIRAnchors( const Function &F, std::map &IRAnchors) { // For inlined code, recover the original callsite and callee by finding the @@ -2718,6 +2784,11 @@ bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM, ProfileSummary::PSK_Sample); PSI->refresh(); } + + if (FunctionSamples::ProfileIsProbeBased && + rejectHighStalenessProfile(M, PSI, Reader->getProfiles())) + return false; + // Compute the total number of samples collected in this profile. for (const auto &I : Reader->getProfiles()) TotalCollectedSamples += I.second.getTotalSamples(); diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch-error.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch-error.ll new file mode 100644 index 000000000000..2bb8f677f40c --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch-error.ll @@ -0,0 +1,7 @@ +; REQUIRES: x86_64-linux +; RUN: not opt < %S/pseudo-probe-profile-mismatch.ll -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-profile-mismatch.prof -min-functions-for-staleness-error=1 -precent-mismatch-for-staleness-error=1 -S 2>&1 | FileCheck %s +; RUN: opt < %S/pseudo-probe-profile-mismatch.ll -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-profile-mismatch.prof -min-functions-for-staleness-error=3 -precent-mismatch-for-staleness-error=70 -S 2>&1 +; RUN: opt < %S/pseudo-probe-profile-mismatch.ll -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-profile-mismatch.prof -min-functions-for-staleness-error=4 -precent-mismatch-for-staleness-error=1 -S 2>&1 + + +; CHECK: error: {{.*}}: The input profile significantly mismatches current source code. Please recollect profile to avoid performance regression. -- GitLab From f1ac559534788f8dd42191b60dfdf9cc56b39fd4 Mon Sep 17 00:00:00 2001 From: ChiaHungDuan Date: Wed, 27 Mar 2024 11:30:08 -0700 Subject: [PATCH 095/541] Revert "[scudo] Use getMonotonicTimeFast for tryLock." (#86590) This reverts commit 36ca9a29025a2f678096e9545fa2ec44e8432592. We were using the `time` as the seed while choosing a new TSD. To make the access of TSDs evenly distributed, we require a higher precision in `time`. Otherwise, many threads may result in having the same random access pattern on TSDs because they share the same `time` in certain period. On Linux, CLOCK_MONOTONIC_COARSE usually adopts 4 ms precision. This is way higher than the average accessing time of TSD (which is usually less than 1 us). As a result, when multiple threads try to select a new TSD in a 4 ms interval, they share the same `time` seed and end up choosing and congesting on the same TSD. --- compiler-rt/lib/scudo/standalone/tsd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler-rt/lib/scudo/standalone/tsd.h b/compiler-rt/lib/scudo/standalone/tsd.h index b2108a01900b..72773f2f72b1 100644 --- a/compiler-rt/lib/scudo/standalone/tsd.h +++ b/compiler-rt/lib/scudo/standalone/tsd.h @@ -41,9 +41,9 @@ template struct alignas(SCUDO_CACHE_LINE_SIZE) TSD { return true; } if (atomic_load_relaxed(&Precedence) == 0) - atomic_store_relaxed(&Precedence, - static_cast(getMonotonicTimeFast() >> - FIRST_32_SECOND_64(16, 0))); + atomic_store_relaxed( + &Precedence, + static_cast(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0))); return false; } inline void lock() NO_THREAD_SAFETY_ANALYSIS { -- GitLab From 36e74cfdbde208e384c72bcb52ea638303fb7d67 Mon Sep 17 00:00:00 2001 From: David Green Date: Wed, 27 Mar 2024 18:36:02 +0000 Subject: [PATCH 096/541] [AArch64] Clear kill flags when removing FMOVDr. (#86308) The uses of OldDef/NewDef may not be killed in the same place they previously were after they are replaced, and so need to be cleared. --- .../Target/AArch64/AArch64MIPeepholeOpt.cpp | 4 +- llvm/test/CodeGen/AArch64/peephole-movd.mir | 60 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/peephole-movd.mir diff --git a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp index 6865850cf04f..22da7ddef98a 100644 --- a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp +++ b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp @@ -680,9 +680,11 @@ bool AArch64MIPeepholeOpt::visitFMOVDr(MachineInstr &MI) { // Let's remove MIs for high 64-bits. Register OldDef = MI.getOperand(0).getReg(); Register NewDef = MI.getOperand(1).getReg(); + LLVM_DEBUG(dbgs() << "Removing: " << MI << "\n"); + MRI->clearKillFlags(OldDef); + MRI->clearKillFlags(NewDef); MRI->constrainRegClass(NewDef, MRI->getRegClass(OldDef)); MRI->replaceRegWith(OldDef, NewDef); - LLVM_DEBUG(dbgs() << "Removed: " << MI << "\n"); MI.eraseFromParent(); return true; diff --git a/llvm/test/CodeGen/AArch64/peephole-movd.mir b/llvm/test/CodeGen/AArch64/peephole-movd.mir new file mode 100644 index 000000000000..bd7f0ab3f044 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/peephole-movd.mir @@ -0,0 +1,60 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -run-pass=aarch64-mi-peephole-opt -o - -mtriple=aarch64-unknown-linux -verify-machineinstrs %s | FileCheck %s + +--- +name: remove_kill_flags +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $w0 + ; CHECK-LABEL: name: remove_kill_flags + ; CHECK: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[MOVIv2d_ns:%[0-9]+]]:fpr128 = MOVIv2d_ns 0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY [[MOVIv2d_ns]].dsub + ; CHECK-NEXT: [[UQSHLv8i8_shift:%[0-9]+]]:fpr64 = UQSHLv8i8_shift killed [[COPY]], 1 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:fpr128 = SUBREG_TO_REG 0, [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: [[TBLv8i8One:%[0-9]+]]:fpr64 = TBLv8i8One killed [[SUBREG_TO_REG]], [[UQSHLv8i8_shift]] + ; CHECK-NEXT: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:fpr128 = MOVIv2d_ns 0 + %1:fpr64 = COPY %0.dsub:fpr128 + %2:fpr64 = UQSHLv8i8_shift killed %1:fpr64, 1 + %3:fpr64 = FMOVDr %2:fpr64 + %4:fpr128 = SUBREG_TO_REG 0, killed %3:fpr64, %subreg.dsub + %5:fpr64 = TBLv8i8One killed %4:fpr128, %2:fpr64 + %7:fpr128 = IMPLICIT_DEF + %6:fpr128 = INSERT_SUBREG %7:fpr128, killed %2:fpr64, %subreg.dsub + RET_ReallyLR implicit $w0 +... +--- +name: remove_kill_flags2 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $w0 + ; CHECK-LABEL: name: remove_kill_flags2 + ; CHECK: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[MOVIv2d_ns:%[0-9]+]]:fpr128 = MOVIv2d_ns 0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY [[MOVIv2d_ns]].dsub + ; CHECK-NEXT: [[UQSHLv8i8_shift:%[0-9]+]]:fpr64 = UQSHLv8i8_shift killed [[COPY]], 1 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:fpr128 = SUBREG_TO_REG 0, [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG1:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF1]], [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:fpr128 = MOVIv2d_ns 0 + %1:fpr64 = COPY %0.dsub:fpr128 + %2:fpr64 = UQSHLv8i8_shift killed %1:fpr64, 1 + %3:fpr64 = FMOVDr %2:fpr64 + %4:fpr128 = SUBREG_TO_REG 0, %3:fpr64, %subreg.dsub + %7:fpr128 = IMPLICIT_DEF + %6:fpr128 = INSERT_SUBREG %7:fpr128, killed %2:fpr64, %subreg.dsub + %9:fpr128 = IMPLICIT_DEF + %8:fpr128 = INSERT_SUBREG %9:fpr128, killed %3:fpr64, %subreg.dsub + RET_ReallyLR implicit $w0 +... + -- GitLab From 2329fb29d141bc356e4b5b859ab290b02f0b3cf6 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <1802579+farzonl@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:51:22 -0400 Subject: [PATCH 097/541] [HLSL] enforce unsigned types for reversebits (#86720) fixes #86719 - `SemaChecking.cpp` - Adds unsigned semaChecks to `__builtin_elementwise_bitreverse` - `hlsl_intrinsics.h` - remove signed `reversebits` apis --- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 31 ---- clang/lib/Sema/SemaChecking.cpp | 13 ++ .../test/CodeGenHLSL/builtins/bitreverse.hlsl | 155 ------------------ .../CodeGenHLSL/builtins/reversebits.hlsl | 75 --------- .../SemaHLSL/BuiltIns/reversebits-errors.hlsl | 12 ++ 5 files changed, 25 insertions(+), 261 deletions(-) delete mode 100644 clang/test/CodeGenHLSL/builtins/bitreverse.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 18472f728eef..d47eab453f87 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1147,19 +1147,6 @@ float4 pow(float4, float4); /// \param Val The input value. #ifdef __HLSL_ENABLE_16_BIT -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t reversebits(int16_t); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t2 reversebits(int16_t2); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t3 reversebits(int16_t3); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t4 reversebits(int16_t4); - _HLSL_AVAILABILITY(shadermodel, 6.2) _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint16_t reversebits(uint16_t); @@ -1174,15 +1161,6 @@ _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint16_t4 reversebits(uint16_t4); #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int reversebits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int2 reversebits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int3 reversebits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int4 reversebits(int4); - _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint reversebits(uint); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) @@ -1192,15 +1170,6 @@ uint3 reversebits(uint3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint4 reversebits(uint4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t reversebits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t2 reversebits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t3 reversebits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t4 reversebits(int64_t4); - _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint64_t reversebits(uint64_t); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 447e73686b4f..f5c0c761da75 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5541,6 +5541,14 @@ bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall) { checkDoubleVector); } +bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall) { + auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool { + return !PassedType->hasUnsignedIntegerRepresentation(); + }; + return CheckArgsTypesAreCorrect(S, TheCall, S->Context.UnsignedIntTy, + checkAllUnsignedTypes); +} + void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, QualType ReturnType) { auto *VecTyA = TheCall->getArg(0)->getType()->getAs(); @@ -5628,6 +5636,11 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } // Note these are llvm builtins that we want to catch invalid intrinsic // generation. Normal handling of these builitns will occur elsewhere. + case Builtin::BI__builtin_elementwise_bitreverse: { + if (CheckUnsignedIntRepresentation(this, TheCall)) + return true; + break; + } case Builtin::BI__builtin_elementwise_cos: case Builtin::BI__builtin_elementwise_sin: case Builtin::BI__builtin_elementwise_log: diff --git a/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl b/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl deleted file mode 100644 index e7609a2b61e2..000000000000 --- a/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl +++ /dev/null @@ -1,155 +0,0 @@ -// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -D__HLSL_ENABLE_16_BIT \ -// RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s - -#ifdef __HLSL_ENABLE_16_BIT -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -int16_t test_bitreverse_short(int16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16( -int16_t2 test_bitreverse_short2(int16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -int16_t3 test_bitreverse_short3(int16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -int16_t4 test_bitreverse_short4(int16_t4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -uint16_t test_bitreverse_ushort(uint16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16 -uint16_t2 test_bitreverse_ushort2(uint16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -uint16_t3 test_bitreverse_ushort3(uint16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -uint16_t4 test_bitreverse_ushort4(uint16_t4 p0) -{ - return reversebits(p0); -} -#endif - -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_int(int p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -int2 test_bitreverse_int2(int2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -int3 test_bitreverse_int3(int3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -int4 test_bitreverse_int4(int4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_uint(uint p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -uint2 test_bitreverse_uint2(uint2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -uint3 test_bitreverse_uint3(uint3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -uint4 test_bitreverse_uint4(uint4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -int64_t test_bitreverse_long(int64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -int64_t2 test_bitreverse_long2(int64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -int64_t3 test_bitreverse_long3(int64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -int64_t4 test_bitreverse_long4(int64_t4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -uint64_t test_bitreverse_long(uint64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -uint64_t2 test_bitreverse_long2(uint64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -uint64_t3 test_bitreverse_long3(uint64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -uint64_t4 test_bitreverse_long4(uint64_t4 p0) -{ - return reversebits(p0); -} diff --git a/clang/test/CodeGenHLSL/builtins/reversebits.hlsl b/clang/test/CodeGenHLSL/builtins/reversebits.hlsl index 6da7d289f82e..a319417e97a4 100644 --- a/clang/test/CodeGenHLSL/builtins/reversebits.hlsl +++ b/clang/test/CodeGenHLSL/builtins/reversebits.hlsl @@ -3,31 +3,6 @@ // RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s #ifdef __HLSL_ENABLE_16_BIT -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -int16_t test_bitreverse_short(int16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16( -int16_t2 test_bitreverse_short2(int16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -int16_t3 test_bitreverse_short3(int16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -int16_t4 test_bitreverse_short4(int16_t4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i16 @ // CHECK: call i16 @llvm.bitreverse.i16( uint16_t test_bitreverse_ushort(uint16_t p0) @@ -54,31 +29,6 @@ uint16_t4 test_bitreverse_ushort4(uint16_t4 p0) } #endif -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_int(int p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -int2 test_bitreverse_int2(int2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -int3 test_bitreverse_int3(int3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -int4 test_bitreverse_int4(int4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i32 @ // CHECK: call i32 @llvm.bitreverse.i32( int test_bitreverse_uint(uint p0) @@ -104,31 +54,6 @@ uint4 test_bitreverse_uint4(uint4 p0) return reversebits(p0); } -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -int64_t test_bitreverse_long(int64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -int64_t2 test_bitreverse_long2(int64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -int64_t3 test_bitreverse_long3(int64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -int64_t4 test_bitreverse_long4(int64_t4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i64 @ // CHECK: call i64 @llvm.bitreverse.i64( uint64_t test_bitreverse_long(uint64_t p0) diff --git a/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl new file mode 100644 index 000000000000..6e66db6d1cca --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify + + +double2 test_int_builtin(double2 p0) { + return __builtin_elementwise_bitreverse(p0); + // expected-error@-1 {{1st argument must be a vector of integers (was 'double2' (aka 'vector'))}} +} + +int2 test_int_builtin(int2 p0) { + return __builtin_elementwise_bitreverse(p0); + // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values)}} +} -- GitLab From 2d641858fa44db315a42fa1b5ba43540f1ca1ea4 Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Wed, 27 Mar 2024 11:57:07 -0700 Subject: [PATCH 098/541] [nfc][PGO]Factor out profile scaling into a standalone helper function (#83780) - Put the helper function in `ProfDataUtil.h/cpp`, which is already a dependency of `Instructions.cpp` - The helper function could be re-used to update profiles of `InvokeInst` (in a follow-up pull request) --- llvm/include/llvm/IR/ProfDataUtils.h | 3 + llvm/lib/IR/Instructions.cpp | 46 +---------- llvm/lib/IR/ProfDataUtils.cpp | 48 +++++++++++ .../Transforms/Inline/update_invoke_prof.ll | 64 +++++++++++++++ .../Transforms/Inline/update_value_profile.ll | 81 +++++++++++++++++++ 5 files changed, 197 insertions(+), 45 deletions(-) create mode 100644 llvm/test/Transforms/Inline/update_invoke_prof.ll create mode 100644 llvm/test/Transforms/Inline/update_value_profile.ll diff --git a/llvm/include/llvm/IR/ProfDataUtils.h b/llvm/include/llvm/IR/ProfDataUtils.h index 255fa2ff1c79..c0897408986f 100644 --- a/llvm/include/llvm/IR/ProfDataUtils.h +++ b/llvm/include/llvm/IR/ProfDataUtils.h @@ -108,5 +108,8 @@ bool extractProfTotalWeight(const Instruction &I, uint64_t &TotalWeights); /// a `prof` metadata reference to instruction `I`. void setBranchWeights(Instruction &I, ArrayRef Weights); +/// Scaling the profile data attached to 'I' using the ratio of S/T. +void scaleProfData(Instruction &I, uint64_t S, uint64_t T); + } // namespace llvm #endif diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index c2abe875e019..cec02e2ce633 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -833,15 +833,6 @@ CallInst *CallInst::Create(CallInst *CI, ArrayRef OpB, // of S/T. The meaning of "branch_weights" meta data for call instruction is // transfered to represent call count. void CallInst::updateProfWeight(uint64_t S, uint64_t T) { - auto *ProfileData = getMetadata(LLVMContext::MD_prof); - if (ProfileData == nullptr) - return; - - auto *ProfDataName = dyn_cast(ProfileData->getOperand(0)); - if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && - !ProfDataName->getString().equals("VP"))) - return; - if (T == 0) { LLVM_DEBUG(dbgs() << "Attempting to update profile weights will result in " "div by 0. Ignoring. Likely the function " @@ -850,42 +841,7 @@ void CallInst::updateProfWeight(uint64_t S, uint64_t T) { "with non-zero prof info."); return; } - - MDBuilder MDB(getContext()); - SmallVector Vals; - Vals.push_back(ProfileData->getOperand(0)); - APInt APS(128, S), APT(128, T); - if (ProfDataName->getString().equals("branch_weights") && - ProfileData->getNumOperands() > 0) { - // Using APInt::div may be expensive, but most cases should fit 64 bits. - APInt Val(128, mdconst::dyn_extract(ProfileData->getOperand(1)) - ->getValue() - .getZExtValue()); - Val *= APS; - Vals.push_back(MDB.createConstant( - ConstantInt::get(Type::getInt32Ty(getContext()), - Val.udiv(APT).getLimitedValue(UINT32_MAX)))); - } else if (ProfDataName->getString().equals("VP")) - for (unsigned i = 1; i < ProfileData->getNumOperands(); i += 2) { - // The first value is the key of the value profile, which will not change. - Vals.push_back(ProfileData->getOperand(i)); - uint64_t Count = - mdconst::dyn_extract(ProfileData->getOperand(i + 1)) - ->getValue() - .getZExtValue(); - // Don't scale the magic number. - if (Count == NOMORE_ICP_MAGICNUM) { - Vals.push_back(ProfileData->getOperand(i + 1)); - continue; - } - // Using APInt::div may be expensive, but most cases should fit 64 bits. - APInt Val(128, Count); - Val *= APS; - Vals.push_back(MDB.createConstant( - ConstantInt::get(Type::getInt64Ty(getContext()), - Val.udiv(APT).getLimitedValue()))); - } - setMetadata(LLVMContext::MD_prof, MDNode::get(getContext(), Vals)); + scaleProfData(*this, S, T); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/IR/ProfDataUtils.cpp b/llvm/lib/IR/ProfDataUtils.cpp index b1a10d0ce5a5..dc86f4204b1a 100644 --- a/llvm/lib/IR/ProfDataUtils.cpp +++ b/llvm/lib/IR/ProfDataUtils.cpp @@ -190,4 +190,52 @@ void setBranchWeights(Instruction &I, ArrayRef Weights) { I.setMetadata(LLVMContext::MD_prof, BranchWeights); } +void scaleProfData(Instruction &I, uint64_t S, uint64_t T) { + assert(T != 0 && "Caller should guarantee"); + auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); + if (ProfileData == nullptr) + return; + + auto *ProfDataName = dyn_cast(ProfileData->getOperand(0)); + if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && + !ProfDataName->getString().equals("VP"))) + return; + + LLVMContext &C = I.getContext(); + + MDBuilder MDB(C); + SmallVector Vals; + Vals.push_back(ProfileData->getOperand(0)); + APInt APS(128, S), APT(128, T); + if (ProfDataName->getString().equals("branch_weights") && + ProfileData->getNumOperands() > 0) { + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, mdconst::dyn_extract(ProfileData->getOperand(1)) + ->getValue() + .getZExtValue()); + Val *= APS; + Vals.push_back(MDB.createConstant(ConstantInt::get( + Type::getInt32Ty(C), Val.udiv(APT).getLimitedValue(UINT32_MAX)))); + } else if (ProfDataName->getString().equals("VP")) + for (unsigned i = 1; i < ProfileData->getNumOperands(); i += 2) { + // The first value is the key of the value profile, which will not change. + Vals.push_back(ProfileData->getOperand(i)); + uint64_t Count = + mdconst::dyn_extract(ProfileData->getOperand(i + 1)) + ->getValue() + .getZExtValue(); + // Don't scale the magic number. + if (Count == NOMORE_ICP_MAGICNUM) { + Vals.push_back(ProfileData->getOperand(i + 1)); + continue; + } + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, Count); + Val *= APS; + Vals.push_back(MDB.createConstant(ConstantInt::get( + Type::getInt64Ty(C), Val.udiv(APT).getLimitedValue()))); + } + I.setMetadata(LLVMContext::MD_prof, MDNode::get(C, Vals)); +} + } // namespace llvm diff --git a/llvm/test/Transforms/Inline/update_invoke_prof.ll b/llvm/test/Transforms/Inline/update_invoke_prof.ll new file mode 100644 index 000000000000..5f09c7cf8fe0 --- /dev/null +++ b/llvm/test/Transforms/Inline/update_invoke_prof.ll @@ -0,0 +1,64 @@ +; A pre-commit test to show that branch weights and value profiles associated with invoke are not updated. +; RUN: opt < %s -passes='require,cgscc(inline)' -S | FileCheck %s + +declare i32 @__gxx_personality_v0(...) + +define void @caller(ptr %func) personality ptr @__gxx_personality_v0 !prof !15 { + call void @callee(ptr %func), !prof !16 + ret void +} + +declare void @inner_callee(ptr %func) + +define void @callee(ptr %func) personality ptr @__gxx_personality_v0 !prof !17 { + invoke void %func() + to label %next unwind label %lpad, !prof !18 + +next: + invoke void @inner_callee(ptr %func) + to label %ret unwind label %lpad, !prof !19 + +lpad: + %exn = landingpad {ptr, i32} + cleanup + unreachable + +ret: + ret void +} + +!llvm.module.flags = !{!1} +!1 = !{i32 1, !"ProfileSummary", !2} +!2 = !{!3, !4, !5, !6, !7, !8, !9, !10} +!3 = !{!"ProfileFormat", !"SampleProfile"} +!4 = !{!"TotalCount", i64 10000} +!5 = !{!"MaxCount", i64 10} +!6 = !{!"MaxInternalCount", i64 1} +!7 = !{!"MaxFunctionCount", i64 2000} +!8 = !{!"NumCounts", i64 2} +!9 = !{!"NumFunctions", i64 2} +!10 = !{!"DetailedSummary", !11} +!11 = !{!12, !13, !14} +!12 = !{i32 10000, i64 100, i32 1} +!13 = !{i32 999000, i64 100, i32 1} +!14 = !{i32 999999, i64 1, i32 2} +!15 = !{!"function_entry_count", i64 1000} +!16 = !{!"branch_weights", i64 1000} +!17 = !{!"function_entry_count", i32 1500} +!18 = !{!"VP", i32 0, i64 1500, i64 123, i64 900, i64 456, i64 600} +!19 = !{!"branch_weights", i32 1500} + +; CHECK-LABEL: @caller( +; CHECK: invoke void %func( +; CHECK-NEXT: {{.*}} !prof ![[PROF1:[0-9]+]] +; CHECK: invoke void @inner_callee( +; CHECK-NEXT: {{.*}} !prof ![[PROF2:[0-9]+]] + +; CHECK-LABL: @callee( +; CHECK: invoke void %func( +; CHECK-NEXT: {{.*}} !prof ![[PROF1]] +; CHECK: invoke void @inner_callee( +; CHECK-NEXT: {{.*}} !prof ![[PROF2]] + +; CHECK: ![[PROF1]] = !{!"VP", i32 0, i64 1500, i64 123, i64 900, i64 456, i64 600} +; CHECK: ![[PROF2]] = !{!"branch_weights", i32 1500} diff --git a/llvm/test/Transforms/Inline/update_value_profile.ll b/llvm/test/Transforms/Inline/update_value_profile.ll new file mode 100644 index 000000000000..daa95e93b68e --- /dev/null +++ b/llvm/test/Transforms/Inline/update_value_profile.ll @@ -0,0 +1,81 @@ +; RUN: opt < %s -passes='require,cgscc(inline)' -inline-threshold=100 -S | FileCheck %s +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; When 'callee' is inlined into caller1 and caller2, the indirect call value +; profiles of the inlined copy should be scaled based on callers' profiles, +; and the indirect call value profiles in 'callee' should be updated. +define i32 @callee(ptr %0, i32 %1) !prof !20 { +; CHECK-LABEL: define i32 @callee( +; CHECK-SAME: ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) !prof [[PROF0:![0-9]+]] { +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8 +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +; CHECK-NEXT: [[TMP6:%.*]] = tail call i32 [[TMP5]](ptr [[TMP0]], i32 [[TMP1]]), !prof [[PROF1:![0-9]+]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %3 = load ptr, ptr %0 + %5 = getelementptr inbounds i8, ptr %3, i64 8 + %6 = load ptr, ptr %5 + %7 = tail call i32 %6(ptr %0, i32 %1), !prof !17 + ret i32 %7 +} + +define i32 @caller1(i32 %0) !prof !18 { +; CHECK-LABEL: define i32 @caller1( +; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF2:![0-9]+]] { +; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @_Z10createTypei(i32 [[TMP0]]) +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8 +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +; CHECK-NEXT: [[TMP6:%.*]] = tail call i32 [[TMP5]](ptr [[TMP2]], i32 [[TMP0]]), !prof [[PROF3:![0-9]+]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = tail call ptr @_Z10createTypei(i32 %0) + %3 = tail call i32 @callee(ptr %2, i32 %0) + ret i32 %3 +} + +define i32 @caller2(i32 %0) !prof !19 { +; CHECK-LABEL: define i32 @caller2( +; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF4:![0-9]+]] { +; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @_Z10createTypei(i32 [[TMP0]]) +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8 +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +; CHECK-NEXT: [[TMP6:%.*]] = tail call i32 [[TMP5]](ptr [[TMP2]], i32 [[TMP0]]), !prof [[PROF5:![0-9]+]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = tail call ptr @_Z10createTypei(i32 %0) + %3 = tail call i32 @callee(ptr %2, i32 %0) + ret i32 %3 +} + +declare ptr @_Z10createTypei(i32) + +!1 = !{i32 1, !"ProfileSummary", !2} +!2 = !{!3, !4, !5, !6, !7, !8, !9, !10} +!3 = !{!"ProfileFormat", !"InstrProf"} +!4 = !{!"TotalCount", i64 10000} +!5 = !{!"MaxCount", i64 10} +!6 = !{!"MaxInternalCount", i64 1} +!7 = !{!"MaxFunctionCount", i64 1000} +!8 = !{!"NumCounts", i64 3} +!9 = !{!"NumFunctions", i64 3} +!10 = !{!"DetailedSummary", !11} +!11 = !{!12, !13, !14} +!12 = !{i32 10000, i64 100, i32 1} +!13 = !{i32 999000, i64 100, i32 1} +!14 = !{i32 999999, i64 1, i32 2} +!17 = !{!"VP", i32 0, i64 1600, i64 123, i64 1000, i64 456, i64 600} +!18 = !{!"function_entry_count", i64 1000} +!19 = !{!"function_entry_count", i64 600} +!20 = !{!"function_entry_count", i64 1700} +;. +; CHECK: [[PROF0]] = !{!"function_entry_count", i64 100} +; CHECK: [[PROF1]] = !{!"VP", i32 0, i64 94, i64 123, i64 58, i64 456, i64 35} +; CHECK: [[PROF2]] = !{!"function_entry_count", i64 1000} +; CHECK: [[PROF3]] = !{!"VP", i32 0, i64 941, i64 123, i64 588, i64 456, i64 352} +; CHECK: [[PROF4]] = !{!"function_entry_count", i64 600} +; CHECK: [[PROF5]] = !{!"VP", i32 0, i64 564, i64 123, i64 352, i64 456, i64 211} +;. -- GitLab From e36ec2f40c7ea998dd11a485b01c32f50b7bf738 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 27 Mar 2024 14:56:44 -0400 Subject: [PATCH 099/541] [C99] Claim conformance to digraphs/iso646 --- clang/test/C/C99/digraphs.c | 90 +++++++++++++++++++++++++++++++++++++ clang/www/c_status.html | 2 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 clang/test/C/C99/digraphs.c diff --git a/clang/test/C/C99/digraphs.c b/clang/test/C/C99/digraphs.c new file mode 100644 index 000000000000..870a44111816 --- /dev/null +++ b/clang/test/C/C99/digraphs.c @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -verify -ffreestanding %s + +/* WG14 ???: yes + * restricted character set support via digraphs and + * + * NB: I cannot find a definitive document number associated with the feature, + * which was pulled from the editor's report in the C99 front matter. However, + * based on discussion in the C99 rationale document, I believe this is + * referring to features added by AMD1 to support ISO 646 and digraphs. + */ + +// Validate that we provide iso646.h in freestanding mode. +#include + +// Validate that we define all the expected macros and their expected +// expansions (when suitable for a constant expression) as well. +#ifndef and +#error "missing and" +#else +_Static_assert((1 and 1) == (1 && 1), ""); +#endif + +#ifndef and_eq +#error "missing and_eq" +#endif + +#ifndef bitand +#error "missing bitand" +#else +_Static_assert((1 bitand 3) == (1 & 3), ""); +#endif + +#ifndef bitor +#error "missing bitor" +#else +_Static_assert((1 bitor 2) == (1 | 2), ""); +#endif + +#ifndef compl +#error "missing compl" +#else +_Static_assert((compl 0) == (~0), ""); +#endif + +#ifndef not +#error "missing not" +#else +_Static_assert((not 12) == (!12), ""); +#endif + +#ifndef not_eq +#error "missing not_eq" +#else +_Static_assert((0 not_eq 12) == (0 != 12), ""); +#endif + +#ifndef or +#error "missing or" +#else +// This intentionally diagnoses use of '||' only, because the user likely did +// not confuse the operator when using 'or' instead. +_Static_assert((0 or 12) == (0 || 12), ""); // expected-warning {{use of logical '||' with constant operand}} \ + expected-note {{use '|' for a bitwise operation}} +#endif + +#ifndef or_eq +#error "missing or_eq" +#endif + +#ifndef xor +#error "missing xor" +#else +_Static_assert((1 xor 3) == (1 ^ 3), ""); +#endif + +#ifndef xor_eq +#error "missing xor_eq" +#endif + +// Validate that digraphs behave the same as their expected counterparts. The +// definition should match the declaration in every way except spelling. +#define DI_NAME(f, b) f %:%: b +#define STD_NAME(f, b) f ## b +void DI_NAME(foo, bar)(int (*array)<: 0 :>); +void STD_NAME(foo, bar)(int (*array)[0]) {} + +#define DI_STR(f) %:f +#define STD_STR(f) #f +_Static_assert(__builtin_strcmp(DI_STR(testing), STD_STR(testing)) == 0, ""); + diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 60f48aba2788..55aca94cd2ec 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -105,7 +105,7 @@ conformance.

restricted character set support via digraphs and <iso646.h> Unknown - Unknown + Yes more precise aliasing rules via effective type -- GitLab From dd06b8e679fd28f51cd065401062041a40b87f9c Mon Sep 17 00:00:00 2001 From: rayroudc Date: Wed, 27 Mar 2024 19:59:31 +0100 Subject: [PATCH 100/541] [clang-format] Fix anonymous reference parameter with default value (#86254) When enabling alignment of consecutive declarations and reference right alignment, the needed space between `& ` and ` = ` is removed in the following use case. Problem (does not compile) ``` int a(const Test &= Test()); double b(); ``` Expected: ``` int a(const Test & = Test()); double b(); ``` Test command: ``` echo "int a(const Test& = Test()); double b();" | clang-format -style="{AlignConsecutiveDeclarations: true, ReferenceAlignment: Right}" ``` --- clang/lib/Format/WhitespaceManager.cpp | 5 +++-- clang/unittests/Format/FormatTest.cpp | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 710bf8d8a8ec..d06c42d5f4c5 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -464,10 +464,11 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, if (i + 1 != Changes.size()) Changes[i + 1].PreviousEndOfTokenColumn += Shift; - // If PointerAlignment is PAS_Right, keep *s or &s next to the token + // If PointerAlignment is PAS_Right, keep *s or &s next to the token, + // except if the token is equal, then a space is needed. if ((Style.PointerAlignment == FormatStyle::PAS_Right || Style.ReferenceAlignment == FormatStyle::RAS_Right) && - CurrentChange.Spaces != 0) { + CurrentChange.Spaces != 0 && CurrentChange.Tok->isNot(tok::equal)) { const bool ReferenceNotRightAligned = Style.ReferenceAlignment != FormatStyle::RAS_Right && Style.ReferenceAlignment != FormatStyle::RAS_Pointer; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 03005384a6f6..d1e977dfa66a 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -19066,6 +19066,11 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { verifyFormat("int a(int x);\n" "double b();", Alignment); + verifyFormat("int a(const Test & = Test());\n" + "int a1(int &foo, const Test & = Test());\n" + "int a2(int &foo, const Test &name = Test());\n" + "double b();", + Alignment); verifyFormat("struct Test {\n" " Test(const Test &) = default;\n" " ~Test() = default;\n" @@ -19102,6 +19107,13 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { " int x,\n" " bool y);", Alignment); + // Set ColumnLimit low so that we break the argument list in multiple lines. + Alignment.ColumnLimit = 35; + verifyFormat("int a3(SomeTypeName1 &x,\n" + " SomeTypeName2 &y,\n" + " const Test & = Test());\n" + "double b();", + Alignment); Alignment.ColumnLimit = OldColumnLimit; // Ensure function pointers don't screw up recursive alignment verifyFormat("int a(int x, void (*fp)(int y));\n" @@ -19287,6 +19299,10 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int foobar;", AlignmentLeft); + verifyFormat("int a(SomeType& foo, const Test& = Test());\n" + "double b();", + AlignmentLeft); + // PAS_Middle FormatStyle AlignmentMiddle = Alignment; AlignmentMiddle.PointerAlignment = FormatStyle::PAS_Middle; @@ -19347,6 +19363,10 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int foobar;", AlignmentMiddle); + verifyFormat("int a(SomeType & foo, const Test & = Test());\n" + "double b();", + AlignmentMiddle); + Alignment.AlignConsecutiveAssignments.Enabled = false; Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; verifyFormat("#define A \\\n" -- GitLab From 421085fd740d937559db068c0a1b354b033aca63 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 27 Mar 2024 14:09:37 -0500 Subject: [PATCH 101/541] [Offload] Change unregister library to use `atexit` instead of destructor (#86830) Summary: The 'new driver' sets up the lifetime of a registered liftime using global constructors and destructors. Currently, this is put at priority 1 which isn't strictly conformant as it will conflict with system utilities. We now use 101 as this is the loweest suggested for non-system constructors and will still run before user constructors. Secondly, there were issues with the CUDA runtime when destructed with a global destructor. Because the global ones are in any order and potentially run before other things we were hitting an edge case where the OpenMP runtime was uninitialized *after* `_dl_fini` was called. This would result in us erroring when we call into a destroyed `libcuda.so` instance. using `atexit` is what CUDA / HIP use and it prevents this from happening. Most everything uses `atexit` except system utilities and because of the constructor priority it will be unregistered *after* everything else but not after `_fl_fini`. --- clang/test/Driver/linker-wrapper-image.c | 8 +-- .../Frontend/Offloading/OffloadWrapper.cpp | 70 ++++++++++--------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 754752641352..d01445e3aed0 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -26,11 +26,11 @@ // OPENMP: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading", align 8 // OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr inbounds ([[[BEGIN:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr getelementptr inbounds ([[[END:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }] // OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries } -// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_reg, ptr null }] -// OPENMP-NEXT: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_unreg, ptr null }] +// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.omp_offloading.descriptor_reg, ptr null }] // OPENMP: define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // OPENMP-NEXT: entry: +// OPENMP-NEXT: %0 = call i32 @atexit(ptr @.omp_offloading.descriptor_unreg) // OPENMP-NEXT: call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) // OPENMP-NEXT: ret void // OPENMP-NEXT: } @@ -62,7 +62,7 @@ // CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 8 // CUDA-NEXT: @.cuda.binary_handle = internal global ptr null -// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.cuda.fatbin_reg, ptr null }] +// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.cuda.fatbin_reg, ptr null }] // CUDA: define internal void @.cuda.fatbin_reg() section ".text.startup" { // CUDA-NEXT: entry: @@ -162,7 +162,7 @@ // HIP-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1212764230, i32 1, ptr @.fatbin_image, ptr null }, section ".hipFatBinSegment", align 8 // HIP-NEXT: @.hip.binary_handle = internal global ptr null -// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.hip.fatbin_reg, ptr null }] +// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.hip.fatbin_reg, ptr null }] // HIP: define internal void @.hip.fatbin_reg() section ".text.startup" { // HIP-NEXT: entry: diff --git a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp index fec1bdbe9d8c..7241d15ed1c6 100644 --- a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp +++ b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp @@ -186,57 +186,62 @@ GlobalVariable *createBinDesc(Module &M, ArrayRef> Bufs, ".omp_offloading.descriptor" + Suffix); } -void createRegisterFunction(Module &M, GlobalVariable *BinDesc, - StringRef Suffix) { +Function *createUnregisterFunction(Module &M, GlobalVariable *BinDesc, + StringRef Suffix) { LLVMContext &C = M.getContext(); auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); - auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, - ".omp_offloading.descriptor_reg" + Suffix, &M); + auto *Func = + Function::Create(FuncTy, GlobalValue::InternalLinkage, + ".omp_offloading.descriptor_unreg" + Suffix, &M); Func->setSection(".text.startup"); - // Get __tgt_register_lib function declaration. - auto *RegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), - /*isVarArg*/ false); - FunctionCallee RegFuncC = - M.getOrInsertFunction("__tgt_register_lib", RegFuncTy); + // Get __tgt_unregister_lib function declaration. + auto *UnRegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), + /*isVarArg*/ false); + FunctionCallee UnRegFuncC = + M.getOrInsertFunction("__tgt_unregister_lib", UnRegFuncTy); // Construct function body IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func)); - Builder.CreateCall(RegFuncC, BinDesc); + Builder.CreateCall(UnRegFuncC, BinDesc); Builder.CreateRetVoid(); - // Add this function to constructors. - // Set priority to 1 so that __tgt_register_lib is executed AFTER - // __tgt_register_requires (we want to know what requirements have been - // asked for before we load a libomptarget plugin so that by the time the - // plugin is loaded it can report how many devices there are which can - // satisfy these requirements). - appendToGlobalCtors(M, Func, /*Priority*/ 1); + return Func; } -void createUnregisterFunction(Module &M, GlobalVariable *BinDesc, - StringRef Suffix) { +void createRegisterFunction(Module &M, GlobalVariable *BinDesc, + StringRef Suffix) { LLVMContext &C = M.getContext(); auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); - auto *Func = - Function::Create(FuncTy, GlobalValue::InternalLinkage, - ".omp_offloading.descriptor_unreg" + Suffix, &M); + auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, + ".omp_offloading.descriptor_reg" + Suffix, &M); Func->setSection(".text.startup"); - // Get __tgt_unregister_lib function declaration. - auto *UnRegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), - /*isVarArg*/ false); - FunctionCallee UnRegFuncC = - M.getOrInsertFunction("__tgt_unregister_lib", UnRegFuncTy); + // Get __tgt_register_lib function declaration. + auto *RegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), + /*isVarArg*/ false); + FunctionCallee RegFuncC = + M.getOrInsertFunction("__tgt_register_lib", RegFuncTy); + + auto *AtExitTy = FunctionType::get( + Type::getInt32Ty(C), PointerType::getUnqual(C), /*isVarArg=*/false); + FunctionCallee AtExit = M.getOrInsertFunction("atexit", AtExitTy); + + Function *UnregFunc = createUnregisterFunction(M, BinDesc, Suffix); // Construct function body IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func)); - Builder.CreateCall(UnRegFuncC, BinDesc); + + // Register the destructors with 'atexit'. This is expected by the CUDA + // runtime and ensures that we clean up before dynamic objects are destroyed. + // This needs to be done before the runtime is called and registers its own. + Builder.CreateCall(AtExit, UnregFunc); + + Builder.CreateCall(RegFuncC, BinDesc); Builder.CreateRetVoid(); - // Add this function to global destructors. - // Match priority of __tgt_register_lib - appendToGlobalDtors(M, Func, /*Priority*/ 1); + // Add this function to constructors. + appendToGlobalCtors(M, Func, /*Priority=*/101); } // struct fatbin_wrapper { @@ -578,7 +583,7 @@ void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc, DtorBuilder.CreateRetVoid(); // Add this function to constructors. - appendToGlobalCtors(M, CtorFunc, /*Priority*/ 1); + appendToGlobalCtors(M, CtorFunc, /*Priority=*/101); } } // namespace @@ -591,7 +596,6 @@ Error offloading::wrapOpenMPBinaries(Module &M, ArrayRef> Images, return createStringError(inconvertibleErrorCode(), "No binary descriptors created."); createRegisterFunction(M, Desc, Suffix); - createUnregisterFunction(M, Desc, Suffix); return Error::success(); } -- GitLab From ed68aac9f225ce560a89315c30f1e97e7e035a03 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 27 Mar 2024 14:10:54 -0500 Subject: [PATCH 102/541] [Libomptarget] Move API implementations into GenericPluginTy (#86683) Summary: The plan is to remove the entire plugin interface and simply use the `GenericPluginTy` inside of `libomptarget` by statically linking against it. This means that inside of `libomptarget` we will simply do `Plugin.data_alloc` without the dynamically loaded interface. To reduce the amount of code required, this patch simply moves all of the RTL implementation functions inside of the Generic device. Now the `__tgt_rtl_` interface is simply a shallow wrapper that will soon go away. There is some redundancy here, this will be improved later. For now what is important is minimizing the changes to the API. --- .../common/include/PluginInterface.h | 126 +++++ .../common/src/PluginInterface.cpp | 465 ++++++++++++------ 2 files changed, 444 insertions(+), 147 deletions(-) diff --git a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h index b16b081e5eff..79e8464bfda5 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h @@ -1065,6 +1065,132 @@ protected: return (DeviceId >= 0 && DeviceId < getNumDevices()); } +public: + // TODO: This plugin interface needs to be cleaned up. + + /// Returns non-zero if the provided \p Image can be executed by the runtime. + int32_t is_valid_binary(__tgt_device_image *Image); + + /// Initialize the device inside of the plugin. + int32_t init_device(int32_t DeviceId); + + /// Return the number of devices this plugin can support. + int32_t number_of_devices(); + + /// Initializes the OpenMP register requires information. + int64_t init_requires(int64_t RequiresFlags); + + /// Returns non-zero if the data can be exchanged between the two devices. + int32_t is_data_exchangable(int32_t SrcDeviceId, int32_t DstDeviceId); + + /// Initializes the record and replay mechanism inside the plugin. + int32_t initialize_record_replay(int32_t DeviceId, int64_t MemorySize, + void *VAddr, bool isRecord, bool SaveOutput, + uint64_t &ReqPtrArgOffset); + + /// Loads the associated binary into the plugin and returns a handle to it. + int32_t load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, + __tgt_device_binary *Binary); + + /// Allocates memory that is accessively to the given device. + void *data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, int32_t Kind); + + /// Deallocates memory on the given device. + int32_t data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind); + + /// Locks / pins host memory using the plugin runtime. + int32_t data_lock(int32_t DeviceId, void *Ptr, int64_t Size, + void **LockedPtr); + + /// Unlocks / unpins host memory using the plugin runtime. + int32_t data_unlock(int32_t DeviceId, void *Ptr); + + /// Notify the runtime about a new mapping that has been created outside. + int32_t data_notify_mapped(int32_t DeviceId, void *HstPtr, int64_t Size); + + /// Notify t he runtime about a mapping that has been deleted. + int32_t data_notify_unmapped(int32_t DeviceId, void *HstPtr); + + /// Copy data to the given device. + int32_t data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr, + int64_t Size); + + /// Copy data to the given device asynchronously. + int32_t data_submit_async(int32_t DeviceId, void *TgtPtr, void *HstPtr, + int64_t Size, __tgt_async_info *AsyncInfoPtr); + + /// Copy data from the given device. + int32_t data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr, + int64_t Size); + + /// Copy data from the given device asynchornously. + int32_t data_retrieve_async(int32_t DeviceId, void *HstPtr, void *TgtPtr, + int64_t Size, __tgt_async_info *AsyncInfoPtr); + + /// Exchange memory addresses between two devices. + int32_t data_exchange(int32_t SrcDeviceId, void *SrcPtr, int32_t DstDeviceId, + void *DstPtr, int64_t Size); + + /// Exchange memory addresses between two devices asynchronously. + int32_t data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, + int DstDeviceId, void *DstPtr, int64_t Size, + __tgt_async_info *AsyncInfo); + + /// Begin executing a kernel on the given device. + int32_t launch_kernel(int32_t DeviceId, void *TgtEntryPtr, void **TgtArgs, + ptrdiff_t *TgtOffsets, KernelArgsTy *KernelArgs, + __tgt_async_info *AsyncInfoPtr); + + /// Synchronize an asyncrhonous queue with the plugin runtime. + int32_t synchronize(int32_t DeviceId, __tgt_async_info *AsyncInfoPtr); + + /// Query the current state of an asynchronous queue. + int32_t query_async(int32_t DeviceId, __tgt_async_info *AsyncInfoPtr); + + /// Prints information about the given devices supported by the plugin. + void print_device_info(int32_t DeviceId); + + /// Creates an event in the given plugin if supported. + int32_t create_event(int32_t DeviceId, void **EventPtr); + + /// Records an event that has occurred. + int32_t record_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr); + + /// Wait until an event has occurred. + int32_t wait_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr); + + /// Syncrhonize execution until an event is done. + int32_t sync_event(int32_t DeviceId, void *EventPtr); + + /// Remove the event from the plugin. + int32_t destroy_event(int32_t DeviceId, void *EventPtr); + + /// Remove the event from the plugin. + void set_info_flag(uint32_t NewInfoLevel); + + /// Creates an asynchronous queue for the given plugin. + int32_t init_async_info(int32_t DeviceId, __tgt_async_info **AsyncInfoPtr); + + /// Creates device information to be used for diagnostics. + int32_t init_device_info(int32_t DeviceId, __tgt_device_info *DeviceInfo, + const char **ErrStr); + + /// Sets the offset into the devices for use by OMPT. + int32_t set_device_offset(int32_t DeviceIdOffset); + + /// Returns if the plugin can support auotmatic copy. + int32_t use_auto_zero_copy(int32_t DeviceId); + + /// Look up a global symbol in the given binary. + int32_t get_global(__tgt_device_binary Binary, uint64_t Size, + const char *Name, void **DevicePtr); + + /// Look up a kernel function in the given binary. + int32_t get_function(__tgt_device_binary Binary, const char *Name, + void **KernelPtr); + private: /// Number of devices available for the plugin. int32_t NumDevices = 0; diff --git a/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp b/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp index c32bd089d8a9..a4e6c9319215 100644 --- a/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp +++ b/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp @@ -1566,36 +1566,7 @@ Expected GenericPluginTy::checkELFImage(StringRef Image) const { return isELFCompatible(Image); } -bool llvm::omp::target::plugin::libomptargetSupportsRPC() { -#ifdef LIBOMPTARGET_RPC_SUPPORT - return true; -#else - return false; -#endif -} - -/// Exposed library API function, basically wrappers around the GenericDeviceTy -/// functionality with the same name. All non-async functions are redirected -/// to the async versions right away with a NULL AsyncInfoPtr. -#ifdef __cplusplus -extern "C" { -#endif - -int32_t __tgt_rtl_init_plugin() { - auto Err = PluginTy::initIfNeeded(); - if (Err) { - [[maybe_unused]] std::string ErrStr = toString(std::move(Err)); - DP("Failed to init plugin: %s", ErrStr.c_str()); - return OFFLOAD_FAIL; - } - - return OFFLOAD_SUCCESS; -} - -int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { - if (!PluginTy::isActive()) - return false; - +int32_t GenericPluginTy::is_valid_binary(__tgt_device_image *Image) { StringRef Buffer(reinterpret_cast(Image->ImageStart), target::getPtrDiff(Image->ImageEnd, Image->ImageStart)); @@ -1610,13 +1581,13 @@ int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { case file_magic::elf_executable: case file_magic::elf_shared_object: case file_magic::elf_core: { - auto MatchOrErr = PluginTy::get().checkELFImage(Buffer); + auto MatchOrErr = checkELFImage(Buffer); if (Error Err = MatchOrErr.takeError()) return HandleError(std::move(Err)); return *MatchOrErr; } case file_magic::bitcode: { - auto MatchOrErr = PluginTy::get().getJIT().checkBitcodeImage(Buffer); + auto MatchOrErr = getJIT().checkBitcodeImage(Buffer); if (Error Err = MatchOrErr.takeError()) return HandleError(std::move(Err)); return *MatchOrErr; @@ -1626,8 +1597,8 @@ int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { } } -int32_t __tgt_rtl_init_device(int32_t DeviceId) { - auto Err = PluginTy::get().initDevice(DeviceId); +int32_t GenericPluginTy::init_device(int32_t DeviceId) { + auto Err = initDevice(DeviceId); if (Err) { REPORT("Failure to initialize device %d: %s\n", DeviceId, toString(std::move(Err)).data()); @@ -1637,26 +1608,24 @@ int32_t __tgt_rtl_init_device(int32_t DeviceId) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_number_of_devices() { - return PluginTy::get().getNumDevices(); -} +int32_t GenericPluginTy::number_of_devices() { return getNumDevices(); } -int64_t __tgt_rtl_init_requires(int64_t RequiresFlags) { - PluginTy::get().setRequiresFlag(RequiresFlags); +int64_t GenericPluginTy::init_requires(int64_t RequiresFlags) { + setRequiresFlag(RequiresFlags); return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_is_data_exchangable(int32_t SrcDeviceId, - int32_t DstDeviceId) { - return PluginTy::get().isDataExchangable(SrcDeviceId, DstDeviceId); +int32_t GenericPluginTy::is_data_exchangable(int32_t SrcDeviceId, + int32_t DstDeviceId) { + return isDataExchangable(SrcDeviceId, DstDeviceId); } -int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, - void *VAddr, bool isRecord, - bool SaveOutput, - uint64_t &ReqPtrArgOffset) { - GenericPluginTy &Plugin = PluginTy::get(); - GenericDeviceTy &Device = Plugin.getDevice(DeviceId); +int32_t GenericPluginTy::initialize_record_replay(int32_t DeviceId, + int64_t MemorySize, + void *VAddr, bool isRecord, + bool SaveOutput, + uint64_t &ReqPtrArgOffset) { + GenericDeviceTy &Device = getDevice(DeviceId); RecordReplayTy::RRStatusTy Status = isRecord ? RecordReplayTy::RRStatusTy::RRRecording : RecordReplayTy::RRStatusTy::RRReplaying; @@ -1675,12 +1644,12 @@ int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, - __tgt_device_binary *Binary) { - GenericPluginTy &Plugin = PluginTy::get(); - GenericDeviceTy &Device = Plugin.getDevice(DeviceId); +int32_t GenericPluginTy::load_binary(int32_t DeviceId, + __tgt_device_image *TgtImage, + __tgt_device_binary *Binary) { + GenericDeviceTy &Device = getDevice(DeviceId); - auto ImageOrErr = Device.loadBinary(Plugin, TgtImage); + auto ImageOrErr = Device.loadBinary(*this, TgtImage); if (!ImageOrErr) { auto Err = ImageOrErr.takeError(); REPORT("Failure to load binary image %p on device %d: %s\n", TgtImage, @@ -1696,10 +1665,10 @@ int32_t __tgt_rtl_load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, return OFFLOAD_SUCCESS; } -void *__tgt_rtl_data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, - int32_t Kind) { - auto AllocOrErr = PluginTy::get().getDevice(DeviceId).dataAlloc( - Size, HostPtr, (TargetAllocTy)Kind); +void *GenericPluginTy::data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, + int32_t Kind) { + auto AllocOrErr = + getDevice(DeviceId).dataAlloc(Size, HostPtr, (TargetAllocTy)Kind); if (!AllocOrErr) { auto Err = AllocOrErr.takeError(); REPORT("Failure to allocate device memory: %s\n", @@ -1711,9 +1680,10 @@ void *__tgt_rtl_data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, return *AllocOrErr; } -int32_t __tgt_rtl_data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind) { - auto Err = PluginTy::get().getDevice(DeviceId).dataDelete( - TgtPtr, (TargetAllocTy)Kind); +int32_t GenericPluginTy::data_delete(int32_t DeviceId, void *TgtPtr, + int32_t Kind) { + auto Err = + getDevice(DeviceId).dataDelete(TgtPtr, static_cast(Kind)); if (Err) { REPORT("Failure to deallocate device pointer %p: %s\n", TgtPtr, toString(std::move(Err)).data()); @@ -1723,9 +1693,9 @@ int32_t __tgt_rtl_data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_lock(int32_t DeviceId, void *Ptr, int64_t Size, - void **LockedPtr) { - auto LockedPtrOrErr = PluginTy::get().getDevice(DeviceId).dataLock(Ptr, Size); +int32_t GenericPluginTy::data_lock(int32_t DeviceId, void *Ptr, int64_t Size, + void **LockedPtr) { + auto LockedPtrOrErr = getDevice(DeviceId).dataLock(Ptr, Size); if (!LockedPtrOrErr) { auto Err = LockedPtrOrErr.takeError(); REPORT("Failure to lock memory %p: %s\n", Ptr, @@ -1742,8 +1712,8 @@ int32_t __tgt_rtl_data_lock(int32_t DeviceId, void *Ptr, int64_t Size, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_unlock(int32_t DeviceId, void *Ptr) { - auto Err = PluginTy::get().getDevice(DeviceId).dataUnlock(Ptr); +int32_t GenericPluginTy::data_unlock(int32_t DeviceId, void *Ptr) { + auto Err = getDevice(DeviceId).dataUnlock(Ptr); if (Err) { REPORT("Failure to unlock memory %p: %s\n", Ptr, toString(std::move(Err)).data()); @@ -1753,9 +1723,9 @@ int32_t __tgt_rtl_data_unlock(int32_t DeviceId, void *Ptr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_notify_mapped(int32_t DeviceId, void *HstPtr, - int64_t Size) { - auto Err = PluginTy::get().getDevice(DeviceId).notifyDataMapped(HstPtr, Size); +int32_t GenericPluginTy::data_notify_mapped(int32_t DeviceId, void *HstPtr, + int64_t Size) { + auto Err = getDevice(DeviceId).notifyDataMapped(HstPtr, Size); if (Err) { REPORT("Failure to notify data mapped %p: %s\n", HstPtr, toString(std::move(Err)).data()); @@ -1765,8 +1735,8 @@ int32_t __tgt_rtl_data_notify_mapped(int32_t DeviceId, void *HstPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_notify_unmapped(int32_t DeviceId, void *HstPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).notifyDataUnmapped(HstPtr); +int32_t GenericPluginTy::data_notify_unmapped(int32_t DeviceId, void *HstPtr) { + auto Err = getDevice(DeviceId).notifyDataUnmapped(HstPtr); if (Err) { REPORT("Failure to notify data unmapped %p: %s\n", HstPtr, toString(std::move(Err)).data()); @@ -1776,17 +1746,16 @@ int32_t __tgt_rtl_data_notify_unmapped(int32_t DeviceId, void *HstPtr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr, - int64_t Size) { - return __tgt_rtl_data_submit_async(DeviceId, TgtPtr, HstPtr, Size, - /*AsyncInfoPtr=*/nullptr); +int32_t GenericPluginTy::data_submit(int32_t DeviceId, void *TgtPtr, + void *HstPtr, int64_t Size) { + return data_submit_async(DeviceId, TgtPtr, HstPtr, Size, + /*AsyncInfoPtr=*/nullptr); } -int32_t __tgt_rtl_data_submit_async(int32_t DeviceId, void *TgtPtr, - void *HstPtr, int64_t Size, - __tgt_async_info *AsyncInfoPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).dataSubmit(TgtPtr, HstPtr, - Size, AsyncInfoPtr); +int32_t GenericPluginTy::data_submit_async(int32_t DeviceId, void *TgtPtr, + void *HstPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).dataSubmit(TgtPtr, HstPtr, Size, AsyncInfoPtr); if (Err) { REPORT("Failure to copy data from host to device. Pointers: host " "= " DPxMOD ", device = " DPxMOD ", size = %" PRId64 ": %s\n", @@ -1798,17 +1767,17 @@ int32_t __tgt_rtl_data_submit_async(int32_t DeviceId, void *TgtPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr, - int64_t Size) { - return __tgt_rtl_data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size, - /*AsyncInfoPtr=*/nullptr); +int32_t GenericPluginTy::data_retrieve(int32_t DeviceId, void *HstPtr, + void *TgtPtr, int64_t Size) { + return data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size, + /*AsyncInfoPtr=*/nullptr); } -int32_t __tgt_rtl_data_retrieve_async(int32_t DeviceId, void *HstPtr, - void *TgtPtr, int64_t Size, - __tgt_async_info *AsyncInfoPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).dataRetrieve( - HstPtr, TgtPtr, Size, AsyncInfoPtr); +int32_t GenericPluginTy::data_retrieve_async(int32_t DeviceId, void *HstPtr, + void *TgtPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + auto Err = + getDevice(DeviceId).dataRetrieve(HstPtr, TgtPtr, Size, AsyncInfoPtr); if (Err) { REPORT("Faliure to copy data from device to host. Pointers: host " "= " DPxMOD ", device = " DPxMOD ", size = %" PRId64 ": %s\n", @@ -1820,20 +1789,19 @@ int32_t __tgt_rtl_data_retrieve_async(int32_t DeviceId, void *HstPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_exchange(int32_t SrcDeviceId, void *SrcPtr, - int32_t DstDeviceId, void *DstPtr, - int64_t Size) { - return __tgt_rtl_data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, - Size, - /*AsyncInfoPtr=*/nullptr); +int32_t GenericPluginTy::data_exchange(int32_t SrcDeviceId, void *SrcPtr, + int32_t DstDeviceId, void *DstPtr, + int64_t Size) { + return data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, Size, + /*AsyncInfoPtr=*/nullptr); } -int32_t __tgt_rtl_data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, - int DstDeviceId, void *DstPtr, - int64_t Size, - __tgt_async_info *AsyncInfo) { - GenericDeviceTy &SrcDevice = PluginTy::get().getDevice(SrcDeviceId); - GenericDeviceTy &DstDevice = PluginTy::get().getDevice(DstDeviceId); +int32_t GenericPluginTy::data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, + int DstDeviceId, void *DstPtr, + int64_t Size, + __tgt_async_info *AsyncInfo) { + GenericDeviceTy &SrcDevice = getDevice(SrcDeviceId); + GenericDeviceTy &DstDevice = getDevice(DstDeviceId); auto Err = SrcDevice.dataExchange(SrcPtr, DstDevice, DstPtr, Size, AsyncInfo); if (Err) { REPORT("Failure to copy data from device (%d) to device (%d). Pointers: " @@ -1846,12 +1814,12 @@ int32_t __tgt_rtl_data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, - void **TgtArgs, ptrdiff_t *TgtOffsets, - KernelArgsTy *KernelArgs, - __tgt_async_info *AsyncInfoPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).launchKernel( - TgtEntryPtr, TgtArgs, TgtOffsets, *KernelArgs, AsyncInfoPtr); +int32_t GenericPluginTy::launch_kernel(int32_t DeviceId, void *TgtEntryPtr, + void **TgtArgs, ptrdiff_t *TgtOffsets, + KernelArgsTy *KernelArgs, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).launchKernel(TgtEntryPtr, TgtArgs, TgtOffsets, + *KernelArgs, AsyncInfoPtr); if (Err) { REPORT("Failure to run target region " DPxMOD " in device %d: %s\n", DPxPTR(TgtEntryPtr), DeviceId, toString(std::move(Err)).data()); @@ -1861,9 +1829,9 @@ int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_synchronize(int32_t DeviceId, - __tgt_async_info *AsyncInfoPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).synchronize(AsyncInfoPtr); +int32_t GenericPluginTy::synchronize(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).synchronize(AsyncInfoPtr); if (Err) { REPORT("Failure to synchronize stream %p: %s\n", AsyncInfoPtr->Queue, toString(std::move(Err)).data()); @@ -1873,9 +1841,9 @@ int32_t __tgt_rtl_synchronize(int32_t DeviceId, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_query_async(int32_t DeviceId, - __tgt_async_info *AsyncInfoPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).queryAsync(AsyncInfoPtr); +int32_t GenericPluginTy::query_async(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).queryAsync(AsyncInfoPtr); if (Err) { REPORT("Failure to query stream %p: %s\n", AsyncInfoPtr->Queue, toString(std::move(Err)).data()); @@ -1885,14 +1853,14 @@ int32_t __tgt_rtl_query_async(int32_t DeviceId, return OFFLOAD_SUCCESS; } -void __tgt_rtl_print_device_info(int32_t DeviceId) { - if (auto Err = PluginTy::get().getDevice(DeviceId).printInfo()) +void GenericPluginTy::print_device_info(int32_t DeviceId) { + if (auto Err = getDevice(DeviceId).printInfo()) REPORT("Failure to print device %d info: %s\n", DeviceId, toString(std::move(Err)).data()); } -int32_t __tgt_rtl_create_event(int32_t DeviceId, void **EventPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).createEvent(EventPtr); +int32_t GenericPluginTy::create_event(int32_t DeviceId, void **EventPtr) { + auto Err = getDevice(DeviceId).createEvent(EventPtr); if (Err) { REPORT("Failure to create event: %s\n", toString(std::move(Err)).data()); return OFFLOAD_FAIL; @@ -1901,10 +1869,9 @@ int32_t __tgt_rtl_create_event(int32_t DeviceId, void **EventPtr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_record_event(int32_t DeviceId, void *EventPtr, - __tgt_async_info *AsyncInfoPtr) { - auto Err = - PluginTy::get().getDevice(DeviceId).recordEvent(EventPtr, AsyncInfoPtr); +int32_t GenericPluginTy::record_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).recordEvent(EventPtr, AsyncInfoPtr); if (Err) { REPORT("Failure to record event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1914,10 +1881,9 @@ int32_t __tgt_rtl_record_event(int32_t DeviceId, void *EventPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_wait_event(int32_t DeviceId, void *EventPtr, - __tgt_async_info *AsyncInfoPtr) { - auto Err = - PluginTy::get().getDevice(DeviceId).waitEvent(EventPtr, AsyncInfoPtr); +int32_t GenericPluginTy::wait_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).waitEvent(EventPtr, AsyncInfoPtr); if (Err) { REPORT("Failure to wait event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1927,8 +1893,8 @@ int32_t __tgt_rtl_wait_event(int32_t DeviceId, void *EventPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_sync_event(int32_t DeviceId, void *EventPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).syncEvent(EventPtr); +int32_t GenericPluginTy::sync_event(int32_t DeviceId, void *EventPtr) { + auto Err = getDevice(DeviceId).syncEvent(EventPtr); if (Err) { REPORT("Failure to synchronize event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1938,8 +1904,8 @@ int32_t __tgt_rtl_sync_event(int32_t DeviceId, void *EventPtr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_destroy_event(int32_t DeviceId, void *EventPtr) { - auto Err = PluginTy::get().getDevice(DeviceId).destroyEvent(EventPtr); +int32_t GenericPluginTy::destroy_event(int32_t DeviceId, void *EventPtr) { + auto Err = getDevice(DeviceId).destroyEvent(EventPtr); if (Err) { REPORT("Failure to destroy event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1949,16 +1915,16 @@ int32_t __tgt_rtl_destroy_event(int32_t DeviceId, void *EventPtr) { return OFFLOAD_SUCCESS; } -void __tgt_rtl_set_info_flag(uint32_t NewInfoLevel) { +void GenericPluginTy::set_info_flag(uint32_t NewInfoLevel) { std::atomic &InfoLevel = getInfoLevelInternal(); InfoLevel.store(NewInfoLevel); } -int32_t __tgt_rtl_init_async_info(int32_t DeviceId, - __tgt_async_info **AsyncInfoPtr) { +int32_t GenericPluginTy::init_async_info(int32_t DeviceId, + __tgt_async_info **AsyncInfoPtr) { assert(AsyncInfoPtr && "Invalid async info"); - auto Err = PluginTy::get().getDevice(DeviceId).initAsyncInfo(AsyncInfoPtr); + auto Err = getDevice(DeviceId).initAsyncInfo(AsyncInfoPtr); if (Err) { REPORT("Failure to initialize async info at " DPxMOD " on device %d: %s\n", DPxPTR(*AsyncInfoPtr), DeviceId, toString(std::move(Err)).data()); @@ -1968,12 +1934,12 @@ int32_t __tgt_rtl_init_async_info(int32_t DeviceId, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_init_device_info(int32_t DeviceId, - __tgt_device_info *DeviceInfo, - const char **ErrStr) { +int32_t GenericPluginTy::init_device_info(int32_t DeviceId, + __tgt_device_info *DeviceInfo, + const char **ErrStr) { *ErrStr = ""; - auto Err = PluginTy::get().getDevice(DeviceId).initDeviceInfo(DeviceInfo); + auto Err = getDevice(DeviceId).initDeviceInfo(DeviceInfo); if (Err) { REPORT("Failure to initialize device info at " DPxMOD " on device %d: %s\n", DPxPTR(DeviceInfo), DeviceId, toString(std::move(Err)).data()); @@ -1983,31 +1949,30 @@ int32_t __tgt_rtl_init_device_info(int32_t DeviceId, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_set_device_offset(int32_t DeviceIdOffset) { - PluginTy::get().setDeviceIdStartIndex(DeviceIdOffset); +int32_t GenericPluginTy::set_device_offset(int32_t DeviceIdOffset) { + setDeviceIdStartIndex(DeviceIdOffset); return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_use_auto_zero_copy(int32_t DeviceId) { +int32_t GenericPluginTy::use_auto_zero_copy(int32_t DeviceId) { // Automatic zero-copy only applies to programs that did // not request unified_shared_memory and are deployed on an // APU with XNACK enabled. - if (PluginTy::get().getRequiresFlags() & OMP_REQ_UNIFIED_SHARED_MEMORY) + if (getRequiresFlags() & OMP_REQ_UNIFIED_SHARED_MEMORY) return false; - return PluginTy::get().getDevice(DeviceId).useAutoZeroCopy(); + return getDevice(DeviceId).useAutoZeroCopy(); } -int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, - const char *Name, void **DevicePtr) { +int32_t GenericPluginTy::get_global(__tgt_device_binary Binary, uint64_t Size, + const char *Name, void **DevicePtr) { assert(Binary.handle && "Invalid device binary handle"); DeviceImageTy &Image = *reinterpret_cast(Binary.handle); - GenericPluginTy &Plugin = PluginTy::get(); GenericDeviceTy &Device = Image.getDevice(); GlobalTy DeviceGlobal(Name, Size); - GenericGlobalHandlerTy &GHandler = Plugin.getGlobalHandler(); + GenericGlobalHandlerTy &GHandler = getGlobalHandler(); if (auto Err = GHandler.getGlobalMetadataFromDevice(Device, Image, DeviceGlobal)) { REPORT("Failure to look up global address: %s\n", @@ -2025,8 +1990,8 @@ int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, - void **KernelPtr) { +int32_t GenericPluginTy::get_function(__tgt_device_binary Binary, + const char *Name, void **KernelPtr) { assert(Binary.handle && "Invalid device binary handle"); DeviceImageTy &Image = *reinterpret_cast(Binary.handle); @@ -2049,6 +2014,212 @@ int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, return OFFLOAD_SUCCESS; } +bool llvm::omp::target::plugin::libomptargetSupportsRPC() { +#ifdef LIBOMPTARGET_RPC_SUPPORT + return true; +#else + return false; +#endif +} + +/// Exposed library API function, basically wrappers around the GenericDeviceTy +/// functionality with the same name. All non-async functions are redirected +/// to the async versions right away with a NULL AsyncInfoPtr. +#ifdef __cplusplus +extern "C" { +#endif + +int32_t __tgt_rtl_init_plugin() { + auto Err = PluginTy::initIfNeeded(); + if (Err) { + [[maybe_unused]] std::string ErrStr = toString(std::move(Err)); + DP("Failed to init plugin: %s", ErrStr.c_str()); + return OFFLOAD_FAIL; + } + + return OFFLOAD_SUCCESS; +} + +int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { + if (!PluginTy::isActive()) + return false; + + return PluginTy::get().is_valid_binary(Image); +} + +int32_t __tgt_rtl_init_device(int32_t DeviceId) { + return PluginTy::get().init_device(DeviceId); +} + +int32_t __tgt_rtl_number_of_devices() { + return PluginTy::get().number_of_devices(); +} + +int64_t __tgt_rtl_init_requires(int64_t RequiresFlags) { + return PluginTy::get().init_requires(RequiresFlags); +} + +int32_t __tgt_rtl_is_data_exchangable(int32_t SrcDeviceId, + int32_t DstDeviceId) { + return PluginTy::get().is_data_exchangable(SrcDeviceId, DstDeviceId); +} + +int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, + void *VAddr, bool isRecord, + bool SaveOutput, + uint64_t &ReqPtrArgOffset) { + return PluginTy::get().initialize_record_replay( + DeviceId, MemorySize, VAddr, isRecord, SaveOutput, ReqPtrArgOffset); +} + +int32_t __tgt_rtl_load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, + __tgt_device_binary *Binary) { + return PluginTy::get().load_binary(DeviceId, TgtImage, Binary); +} + +void *__tgt_rtl_data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, + int32_t Kind) { + return PluginTy::get().data_alloc(DeviceId, Size, HostPtr, Kind); +} + +int32_t __tgt_rtl_data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind) { + return PluginTy::get().data_delete(DeviceId, TgtPtr, Kind); +} + +int32_t __tgt_rtl_data_lock(int32_t DeviceId, void *Ptr, int64_t Size, + void **LockedPtr) { + return PluginTy::get().data_lock(DeviceId, Ptr, Size, LockedPtr); +} + +int32_t __tgt_rtl_data_unlock(int32_t DeviceId, void *Ptr) { + return PluginTy::get().data_unlock(DeviceId, Ptr); +} + +int32_t __tgt_rtl_data_notify_mapped(int32_t DeviceId, void *HstPtr, + int64_t Size) { + return PluginTy::get().data_notify_mapped(DeviceId, HstPtr, Size); +} + +int32_t __tgt_rtl_data_notify_unmapped(int32_t DeviceId, void *HstPtr) { + return PluginTy::get().data_notify_unmapped(DeviceId, HstPtr); +} + +int32_t __tgt_rtl_data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr, + int64_t Size) { + return PluginTy::get().data_submit(DeviceId, TgtPtr, HstPtr, Size); +} + +int32_t __tgt_rtl_data_submit_async(int32_t DeviceId, void *TgtPtr, + void *HstPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().data_submit_async(DeviceId, TgtPtr, HstPtr, Size, + AsyncInfoPtr); +} + +int32_t __tgt_rtl_data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr, + int64_t Size) { + return PluginTy::get().data_retrieve(DeviceId, HstPtr, TgtPtr, Size); +} + +int32_t __tgt_rtl_data_retrieve_async(int32_t DeviceId, void *HstPtr, + void *TgtPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size, + AsyncInfoPtr); +} + +int32_t __tgt_rtl_data_exchange(int32_t SrcDeviceId, void *SrcPtr, + int32_t DstDeviceId, void *DstPtr, + int64_t Size) { + return PluginTy::get().data_exchange(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, + Size); +} + +int32_t __tgt_rtl_data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, + int DstDeviceId, void *DstPtr, + int64_t Size, + __tgt_async_info *AsyncInfo) { + return PluginTy::get().data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, + DstPtr, Size, AsyncInfo); +} + +int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, + void **TgtArgs, ptrdiff_t *TgtOffsets, + KernelArgsTy *KernelArgs, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().launch_kernel(DeviceId, TgtEntryPtr, TgtArgs, + TgtOffsets, KernelArgs, AsyncInfoPtr); +} + +int32_t __tgt_rtl_synchronize(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().synchronize(DeviceId, AsyncInfoPtr); +} + +int32_t __tgt_rtl_query_async(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().query_async(DeviceId, AsyncInfoPtr); +} + +void __tgt_rtl_print_device_info(int32_t DeviceId) { + PluginTy::get().print_device_info(DeviceId); +} + +int32_t __tgt_rtl_create_event(int32_t DeviceId, void **EventPtr) { + return PluginTy::get().create_event(DeviceId, EventPtr); +} + +int32_t __tgt_rtl_record_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().record_event(DeviceId, EventPtr, AsyncInfoPtr); +} + +int32_t __tgt_rtl_wait_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().wait_event(DeviceId, EventPtr, AsyncInfoPtr); +} + +int32_t __tgt_rtl_sync_event(int32_t DeviceId, void *EventPtr) { + return PluginTy::get().sync_event(DeviceId, EventPtr); +} + +int32_t __tgt_rtl_destroy_event(int32_t DeviceId, void *EventPtr) { + return PluginTy::get().destroy_event(DeviceId, EventPtr); +} + +void __tgt_rtl_set_info_flag(uint32_t NewInfoLevel) { + return PluginTy::get().set_info_flag(NewInfoLevel); +} + +int32_t __tgt_rtl_init_async_info(int32_t DeviceId, + __tgt_async_info **AsyncInfoPtr) { + return PluginTy::get().init_async_info(DeviceId, AsyncInfoPtr); +} + +int32_t __tgt_rtl_init_device_info(int32_t DeviceId, + __tgt_device_info *DeviceInfo, + const char **ErrStr) { + return PluginTy::get().init_device_info(DeviceId, DeviceInfo, ErrStr); +} + +int32_t __tgt_rtl_set_device_offset(int32_t DeviceIdOffset) { + return PluginTy::get().set_device_offset(DeviceIdOffset); +} + +int32_t __tgt_rtl_use_auto_zero_copy(int32_t DeviceId) { + return PluginTy::get().use_auto_zero_copy(DeviceId); +} + +int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, + const char *Name, void **DevicePtr) { + return PluginTy::get().get_global(Binary, Size, Name, DevicePtr); +} + +int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, + void **KernelPtr) { + return PluginTy::get().get_function(Binary, Name, KernelPtr); +} + #ifdef __cplusplus } #endif -- GitLab From 6ef829941b38f7e8a28c4cba1ff25cd0ae9f7d3d Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 27 Mar 2024 19:11:17 +0000 Subject: [PATCH 103/541] Recommit "[VPlan] Replace disjoint or with add instead of dropping disjoint. (#83821)" Recommit with a fix for the use-after-free causing the revert. This reverts the revert commit f872043e055f4163c3c4b1b86ca0354490174987. Original commit message: Dropping disjoint from an OR may yield incorrect results, as some analysis may have converted it to an Add implicitly (e.g. SCEV used for dependence analysis). Instead, replace it with an equivalent Add. This is possible as all users of the disjoint OR only access lanes where the operands are disjoint or poison otherwise. Note that replacing all disjoint ORs with ADDs instead of dropping the flags is not strictly necessary. It is only needed for disjoint ORs that SCEV treated as ADDs, but those are not tracked. There are other places that may drop poison-generating flags; those likely need similar treatment. Fixes https://github.com/llvm/llvm-project/issues/81872 PR: https://github.com/llvm/llvm-project/pull/83821 --- .../Vectorize/LoopVectorizationPlanner.h | 3 +++ llvm/lib/Transforms/Vectorize/VPlan.h | 6 ++++++ .../Transforms/Vectorize/VPlanPatternMatch.h | 5 +++++ .../Transforms/Vectorize/VPlanTransforms.cpp | 19 ++++++++++++++++++- .../Transforms/LoopVectorize/X86/pr81872.ll | 2 +- 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index e86705e89889..5d03b66b0ce3 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -68,6 +68,9 @@ class VPBuilder { public: VPBuilder() = default; VPBuilder(VPBasicBlock *InsertBB) { setInsertPoint(InsertBB); } + VPBuilder(VPRecipeBase *InsertPt) { + setInsertPoint(InsertPt->getParent(), InsertPt->getIterator()); + } /// Clear the insertion point: created instructions will not be inserted into /// a block. diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index f70ccf8270b2..2f56799a7b51 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1127,6 +1127,12 @@ public: return WrapFlags.HasNSW; } + bool isDisjoint() const { + assert(OpType == OperationType::DisjointOp && + "recipe cannot have a disjoing flag"); + return DisjointFlags.IsDisjoint; + } + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void printFlags(raw_ostream &O) const; #endif diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index aa2535906945..a03a408686ef 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -261,6 +261,11 @@ m_Mul(const Op0_t &Op0, const Op1_t &Op1) { return m_Binary(Op0, Op1); } +template +inline AllBinaryRecipe_match +m_Or(const Op0_t &Op0, const Op1_t &Op1) { + return m_Binary(Op0, Op1); +} } // namespace VPlanPatternMatch } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index e6ab27a918bc..006f4349d6fb 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -1255,7 +1255,24 @@ void VPlanTransforms::dropPoisonGeneratingRecipes( // load/store. If the underlying instruction has poison-generating flags, // drop them directly. if (auto *RecWithFlags = dyn_cast(CurRec)) { - RecWithFlags->dropPoisonGeneratingFlags(); + VPValue *A, *B; + using namespace llvm::VPlanPatternMatch; + // Dropping disjoint from an OR may yield incorrect results, as some + // analysis may have converted it to an Add implicitly (e.g. SCEV used + // for dependence analysis). Instead, replace it with an equivalent Add. + // This is possible as all users of the disjoint OR only access lanes + // where the operands are disjoint or poison otherwise. + if (match(RecWithFlags, m_Or(m_VPValue(A), m_VPValue(B))) && + RecWithFlags->isDisjoint()) { + VPBuilder Builder(RecWithFlags); + VPInstruction *New = Builder.createOverflowingOp( + Instruction::Add, {A, B}, {false, false}, + RecWithFlags->getDebugLoc()); + RecWithFlags->replaceAllUsesWith(New); + RecWithFlags->eraseFromParent(); + CurRec = New; + } else + RecWithFlags->dropPoisonGeneratingFlags(); } else { Instruction *Instr = dyn_cast_or_null( CurRec->getVPSingleValue()->getUnderlyingValue()); diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll index 14acb6f57aa0..3f38abc75a58 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll @@ -29,7 +29,7 @@ define void @test(ptr noundef align 8 dereferenceable_or_null(16) %arr) #0 { ; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i64> [[VEC_IND]], ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <4 x i64> [[TMP2]], zeroinitializer ; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP1]], <4 x i1> [[TMP3]], <4 x i1> zeroinitializer -; CHECK-NEXT: [[TMP5:%.*]] = or i64 [[TMP0]], 1 +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP0]], 1 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, ptr [[ARR]], i64 [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[TMP6]], i32 0 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i64, ptr [[TMP7]], i32 -3 -- GitLab From c2bdbedf1c2326cb3b38cedf0ee46413d86e2e2c Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 27 Mar 2024 15:13:05 -0400 Subject: [PATCH 104/541] [libc++][NFC] Remove whitespace that doesn't belong --- libcxx/utils/libcxx/test/params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index 695e01115aa4..5e42562ed5db 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -407,6 +407,6 @@ DEFAULT_PARAMETERS = [ AddFeature('has-clang-tidy'), AddSubstitution('%{clang-tidy}', exe), ] - ), + ), ] # fmt: on -- GitLab From aeb8628c218f8224e08dddcdd3199a445d8607a8 Mon Sep 17 00:00:00 2001 From: Neumann Hon Date: Wed, 27 Mar 2024 15:15:32 -0400 Subject: [PATCH 105/541] Revert "[SystemZ][z/OS] TXT records in the GOFF reader (#74526)" This reverts commit 009f88fc0e3a036be97ef7b222b90af342bae0b7. Reverting PR due to test failure. --- llvm/include/llvm/Object/GOFF.h | 20 ---- llvm/include/llvm/Object/GOFFObjectFile.h | 56 +++-------- llvm/lib/Object/GOFFObjectFile.cpp | 19 ---- llvm/unittests/Object/GOFFObjectFileTest.cpp | 97 -------------------- 4 files changed, 14 insertions(+), 178 deletions(-) diff --git a/llvm/include/llvm/Object/GOFF.h b/llvm/include/llvm/Object/GOFF.h index 9fb8876e893d..91762457ae05 100644 --- a/llvm/include/llvm/Object/GOFF.h +++ b/llvm/include/llvm/Object/GOFF.h @@ -73,26 +73,6 @@ protected: } }; -class TXTRecord : public Record { -public: - /// \brief Maximum length of data; any more must go in continuation. - static const uint8_t TXTMaxDataLength = 56; - - static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); - - static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) { - get(Record, 4, EsdId); - } - - static void getOffset(const uint8_t *Record, uint32_t &Offset) { - get(Record, 12, Offset); - } - - static void getDataLength(const uint8_t *Record, uint16_t &Length) { - get(Record, 22, Length); - } -}; - class HDRRecord : public Record { public: static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); diff --git a/llvm/include/llvm/Object/GOFFObjectFile.h b/llvm/include/llvm/Object/GOFFObjectFile.h index 6871641e97ec..7e1ceb95f667 100644 --- a/llvm/include/llvm/Object/GOFFObjectFile.h +++ b/llvm/include/llvm/Object/GOFFObjectFile.h @@ -29,10 +29,7 @@ namespace llvm { namespace object { class GOFFObjectFile : public ObjectFile { - friend class GOFFSymbolRef; - IndexedMap EsdPtrs; // Indexed by EsdId. - SmallVector TextPtrs; mutable DenseMap>> EsdNamesCache; @@ -41,7 +38,7 @@ class GOFFObjectFile : public ObjectFile { // (EDID, 0) code, r/o data section // (EDID,PRID) r/w data section SmallVector SectionList; - mutable DenseMap> SectionDataCache; + mutable DenseMap SectionDataCache; public: Expected getSymbolName(SymbolRef Symbol) const; @@ -69,10 +66,6 @@ public: return true; } - bool isSectionNoLoad(DataRefImpl Sec) const; - bool isSectionReadOnlyData(DataRefImpl Sec) const; - bool isSectionZeroInit(DataRefImpl Sec) const; - private: // SymbolRef. Expected getSymbolName(DataRefImpl Symb) const override; @@ -82,24 +75,27 @@ private: Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; - uint64_t getSymbolSize(DataRefImpl Symb) const; const uint8_t *getSymbolEsdRecord(DataRefImpl Symb) const; bool isSymbolUnresolved(DataRefImpl Symb) const; bool isSymbolIndirect(DataRefImpl Symb) const; // SectionRef. - void moveSectionNext(DataRefImpl &Sec) const override; - virtual Expected getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; + void moveSectionNext(DataRefImpl &Sec) const override {} + virtual Expected getSectionName(DataRefImpl Sec) const override { + return StringRef(); + } + uint64_t getSectionAddress(DataRefImpl Sec) const override { return 0; } + uint64_t getSectionSize(DataRefImpl Sec) const override { return 0; } virtual Expected> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override { return Sec.d.a; } - uint64_t getSectionAlignment(DataRefImpl Sec) const override; + getSectionContents(DataRefImpl Sec) const override { + return ArrayRef(); + } + uint64_t getSectionIndex(DataRefImpl Sec) const override { return 0; } + uint64_t getSectionAlignment(DataRefImpl Sec) const override { return 0; } bool isSectionCompressed(DataRefImpl Sec) const override { return false; } - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override { return false; } + bool isSectionData(DataRefImpl Sec) const override { return false; } bool isSectionBSS(DataRefImpl Sec) const override { return false; } bool isSectionVirtual(DataRefImpl Sec) const override { return false; } relocation_iterator section_rel_begin(DataRefImpl Sec) const override { @@ -113,7 +109,6 @@ private: const uint8_t *getSectionPrEsdRecord(DataRefImpl &Sec) const; const uint8_t *getSectionEdEsdRecord(uint32_t SectionIndex) const; const uint8_t *getSectionPrEsdRecord(uint32_t SectionIndex) const; - uint32_t getSectionDefEsdId(DataRefImpl &Sec) const; // RelocationRef. void moveRelocationNext(DataRefImpl &Rel) const override {} @@ -127,29 +122,6 @@ private: SmallVectorImpl &Result) const override {} }; -class GOFFSymbolRef : public SymbolRef { -public: - GOFFSymbolRef(const SymbolRef &B) : SymbolRef(B) { - assert(isa(SymbolRef::getObject())); - } - - const GOFFObjectFile *getObject() const { - return cast(BasicSymbolRef::getObject()); - } - - Expected getSymbolGOFFFlags() const { - return getObject()->getSymbolFlags(getRawDataRefImpl()); - } - - Expected getSymbolGOFFType() const { - return getObject()->getSymbolType(getRawDataRefImpl()); - } - - uint64_t getSize() const { - return getObject()->getSymbolSize(getRawDataRefImpl()); - } -}; - } // namespace object } // namespace llvm diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp index 2845d9362544..d8e1ddf2aef8 100644 --- a/llvm/lib/Object/GOFFObjectFile.cpp +++ b/llvm/lib/Object/GOFFObjectFile.cpp @@ -168,11 +168,6 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n"); break; } - case GOFF::RT_TXT: - // Save TXT records. - TextPtrs.emplace_back(I); - LLVM_DEBUG(dbgs() << " -- TXT\n"); - break; case GOFF::RT_END: LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n"); break; @@ -369,13 +364,6 @@ GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { std::to_string(SymEdId)); } -uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { - const uint8_t *Record = getSymbolEsdRecord(Symb); - uint32_t Length; - ESDRecord::getLength(Record, Length); - return Length; -} - const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const { SectionEntryImpl EsdIds = SectionList[Sec.d.a]; const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a]; @@ -636,13 +624,6 @@ Error ESDRecord::getData(const uint8_t *Record, return getContinuousData(Record, DataSize, 72, CompleteData); } -Error TXTRecord::getData(const uint8_t *Record, - SmallString<256> &CompleteData) { - uint16_t Length; - getDataLength(Record, Length); - return getContinuousData(Record, Length, 24, CompleteData); -} - Error ENDRecord::getData(const uint8_t *Record, SmallString<256> &CompleteData) { uint16_t Length = getNameLength(Record); diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp index 69f60d016a80..734dac6b8507 100644 --- a/llvm/unittests/Object/GOFFObjectFileTest.cpp +++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp @@ -502,100 +502,3 @@ TEST(GOFFObjectFileTest, InvalidERSymbolType) { FailedWithMessage("ESD record 1 has unknown Executable type 0x03")); } } - -TEST(GOFFObjectFileTest, TXTConstruct) { - char GOFFData[GOFF::RecordLength * 6] = {}; - - // HDR record. - GOFFData[0] = 0x03; - GOFFData[1] = 0xF0; - GOFFData[50] = 0x01; - - // ESD record. - GOFFData[GOFF::RecordLength] = 0x03; - GOFFData[GOFF::RecordLength + 7] = 0x01; // ESDID. - GOFFData[GOFF::RecordLength + 71] = 0x05; // Size of symbol name. - GOFFData[GOFF::RecordLength + 72] = 0xa5; // Symbol name is v. - GOFFData[GOFF::RecordLength + 73] = 0x81; // Symbol name is a. - GOFFData[GOFF::RecordLength + 74] = 0x99; // Symbol name is r. - GOFFData[GOFF::RecordLength + 75] = 0x7b; // Symbol name is #. - GOFFData[GOFF::RecordLength + 76] = 0x83; // Symbol name is c. - - // ESD record. - GOFFData[GOFF::RecordLength * 2] = 0x03; - GOFFData[GOFF::RecordLength * 2 + 3] = 0x01; - GOFFData[GOFF::RecordLength * 2 + 7] = 0x02; // ESDID. - GOFFData[GOFF::RecordLength * 2 + 11] = 0x01; // Parent ESDID. - GOFFData[GOFF::RecordLength * 2 + 27] = 0x08; // Length. - GOFFData[GOFF::RecordLength * 2 + 40] = 0x01; // Name Space ID. - GOFFData[GOFF::RecordLength * 2 + 41] = 0x80; - GOFFData[GOFF::RecordLength * 2 + 60] = 0x04; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 61] = 0x04; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 63] = 0x0a; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 66] = 0x03; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 71] = 0x08; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 72] = 0xc3; // Symbol name is c. - GOFFData[GOFF::RecordLength * 2 + 73] = 0x6d; // Symbol name is _. - GOFFData[GOFF::RecordLength * 2 + 74] = 0xc3; // Symbol name is c. - GOFFData[GOFF::RecordLength * 2 + 75] = 0xd6; // Symbol name is o. - GOFFData[GOFF::RecordLength * 2 + 76] = 0xc4; // Symbol name is D. - GOFFData[GOFF::RecordLength * 2 + 77] = 0xc5; // Symbol name is E. - GOFFData[GOFF::RecordLength * 2 + 78] = 0xf6; // Symbol name is 6. - GOFFData[GOFF::RecordLength * 2 + 79] = 0xf4; // Symbol name is 4. - - // ESD record. - GOFFData[GOFF::RecordLength * 3] = 0x03; - GOFFData[GOFF::RecordLength * 3 + 3] = 0x02; - GOFFData[GOFF::RecordLength * 3 + 7] = 0x03; // ESDID. - GOFFData[GOFF::RecordLength * 3 + 11] = 0x02; // Parent ESDID. - GOFFData[GOFF::RecordLength * 3 + 71] = 0x05; // Size of symbol name. - GOFFData[GOFF::RecordLength * 3 + 72] = 0xa5; // Symbol name is v. - GOFFData[GOFF::RecordLength * 3 + 73] = 0x81; // Symbol name is a. - GOFFData[GOFF::RecordLength * 3 + 74] = 0x99; // Symbol name is r. - GOFFData[GOFF::RecordLength * 3 + 75] = 0x7b; // Symbol name is #. - GOFFData[GOFF::RecordLength * 3 + 76] = 0x83; // Symbol name is c. - - // TXT record. - GOFFData[GOFF::RecordLength * 4] = 0x03; - GOFFData[GOFF::RecordLength * 4 + 1] = 0x10; - GOFFData[GOFF::RecordLength * 4 + 7] = 0x02; - GOFFData[GOFF::RecordLength * 4 + 23] = 0x08; // Data Length. - GOFFData[GOFF::RecordLength * 4 + 24] = 0x12; - GOFFData[GOFF::RecordLength * 4 + 25] = 0x34; - GOFFData[GOFF::RecordLength * 4 + 26] = 0x56; - GOFFData[GOFF::RecordLength * 4 + 27] = 0x78; - GOFFData[GOFF::RecordLength * 4 + 28] = 0x9a; - GOFFData[GOFF::RecordLength * 4 + 29] = 0xbc; - GOFFData[GOFF::RecordLength * 4 + 30] = 0xde; - GOFFData[GOFF::RecordLength * 4 + 31] = 0xf0; - - // END record. - GOFFData[GOFF::RecordLength * 5] = 0x03; - GOFFData[GOFF::RecordLength * 5 + 1] = 0x40; - GOFFData[GOFF::RecordLength * 5 + 11] = 0x06; - - StringRef Data(GOFFData, GOFF::RecordLength * 6); - - Expected> GOFFObjOrErr = - object::ObjectFile::createGOFFObjectFile( - MemoryBufferRef(Data, "dummyGOFF")); - - ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded()); - - GOFFObjectFile *GOFFObj = dyn_cast((*GOFFObjOrErr).get()); - auto Symbols = GOFFObj->symbols(); - ASSERT_EQ(std::distance(Symbols.begin(), Symbols.end()), 1); - SymbolRef Symbol = *Symbols.begin(); - Expected SymbolNameOrErr = GOFFObj->getSymbolName(Symbol); - ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded()); - StringRef SymbolName = SymbolNameOrErr.get(); - EXPECT_EQ(SymbolName, "var#c"); - - auto Sections = GOFFObj->sections(); - ASSERT_EQ(std::distance(Sections.begin(), Sections.end()), 1); - SectionRef Section = *Sections.begin(); - Expected SectionContent = Section.getContents(); - ASSERT_THAT_EXPECTED(SectionContent, Succeeded()); - StringRef Contents = SectionContent.get(); - EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0"); -} -- GitLab From baf66ec061aa4da85d6bdfd1f9cd1030b9607fbb Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Mar 2024 12:19:28 -0700 Subject: [PATCH 106/541] [Target][RISCV] Add HwMode support to subregister index size/offset. (#86368) This is needed to provide proper size and offset for the GPRPair subreg indices on RISC-V. The size of a GPR already uses HwMode. Previously we said the subreg indices have unknown size and offset, but this stops DwarfExpression::addMachineReg from being able to find the registers that make up the pair. I believe this fixes https://github.com/llvm/llvm-project/issues/85864 but need to verify. --- llvm/include/llvm/Target/Target.td | 17 ++++ llvm/lib/CodeGen/TargetRegisterInfo.cpp | 4 +- llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 11 ++- llvm/test/TableGen/ConcatenatedSubregs.td | 9 ++- llvm/test/TableGen/HwModeSubRegs.td | 75 ++++++++++++++++++ .../TableGen/Common/CodeGenRegisters.cpp | 79 +++++++++++++------ llvm/utils/TableGen/Common/CodeGenRegisters.h | 43 +++++++--- llvm/utils/TableGen/Common/InfoByHwMode.cpp | 14 ++++ llvm/utils/TableGen/Common/InfoByHwMode.h | 21 ++++- llvm/utils/TableGen/RegisterInfoEmitter.cpp | 19 +++-- 10 files changed, 242 insertions(+), 50 deletions(-) create mode 100644 llvm/test/TableGen/HwModeSubRegs.td diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index cb1c0ed2513d..1f7dc6922f13 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -83,10 +83,27 @@ class RegInfoByHwMode Ms = [], list Ts = []> list Objects = Ts; } +class SubRegRange { + int Size = size; // Sub register size in bits. + int Offset = offset; // Offset of the first bit of the sub-reg index. +} + +class SubRegRangeByHwMode Ms = [], list Ts = []> + : HwModeSelect { + // The length of this list must be the same as the length of Ms. + list Objects = Ts; +} + // SubRegIndex - Use instances of SubRegIndex to identify subregisters. class SubRegIndex { string Namespace = ""; + // The size/offset information, parameterized by a HW mode. + // If the HwModes provided for SubRegRanges does not include the DefaultMode, + // the/ Size and Offset fields below will be used for the default. Otherwise, + // the Size and Offset fields are ignored. + SubRegRangeByHwMode SubRegRanges; + // Size - Size (in bits) of the sub-registers represented by this index. int Size = size; diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp index 4120c74c23b1..4e06393f4cc1 100644 --- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp +++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp @@ -595,13 +595,13 @@ bool TargetRegisterInfo::getCoveringSubRegIndexes( unsigned TargetRegisterInfo::getSubRegIdxSize(unsigned Idx) const { assert(Idx && Idx < getNumSubRegIndices() && "This is not a subregister index"); - return SubRegIdxRanges[Idx].Size; + return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Size; } unsigned TargetRegisterInfo::getSubRegIdxOffset(unsigned Idx) const { assert(Idx && Idx < getNumSubRegIndices() && "This is not a subregister index"); - return SubRegIdxRanges[Idx].Offset; + return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Offset; } Register diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 9da1f73681c6..90c4a7193ee3 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -64,9 +64,14 @@ def sub_vrm1_6 : ComposedSubRegIndex; def sub_vrm1_7 : ComposedSubRegIndex; // GPR sizes change with HwMode. -// FIXME: Support HwMode in SubRegIndex? -def sub_gpr_even : SubRegIndex<-1>; -def sub_gpr_odd : SubRegIndex<-1, -1>; +def sub_gpr_even : SubRegIndex<32> { + let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64], + [SubRegRange<32>, SubRegRange<64>]>; +} +def sub_gpr_odd : SubRegIndex<32, 32> { + let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64], + [SubRegRange<32, 32>, SubRegRange<64, 64>]>; +} } // Namespace = "RISCV" // Integer registers diff --git a/llvm/test/TableGen/ConcatenatedSubregs.td b/llvm/test/TableGen/ConcatenatedSubregs.td index 5b354c94dca5..ea4e7f01a2e2 100644 --- a/llvm/test/TableGen/ConcatenatedSubregs.td +++ b/llvm/test/TableGen/ConcatenatedSubregs.td @@ -90,16 +90,19 @@ def TestTarget : Target; // CHECK-LABEL: RegisterClass DRegs: // CHECK-LABEL: SubRegIndex ssub1: -// CHECK: Offset, Size: 16, 16 +// CHECK: Offset: { Default:16 } +// CHECK: Size: { Default:16 } // CHECK-LABEL: SubRegIndex sub0: // CHECK-LABEL: SubRegIndex sub1: // CHECK-LABEL: SubRegIndex sub2: // Check inferred indexes: // CHECK-LABEL: SubRegIndex ssub1_ssub2: -// CHECK: Offset, Size: 16, 65535 +// CHECK: Offset: { Default:16 } +// CHECK: Size: { Default:65535 } // CHECK-LABEL: SubRegIndex ssub3_ssub4: // CHECK-LABEL: SubRegIndex ssub0_ssub1_ssub2_ssub3: -// CHECK: Offset, Size: 65535, 65535 +// CHECK: Offset: { Default:65535 } +// CHECK: Size: { Default:65535 } // CHECK-LABEL: SubRegIndex ssub1_ssub2_ssub3_ssub4: // Check that all subregs are generated on some examples diff --git a/llvm/test/TableGen/HwModeSubRegs.td b/llvm/test/TableGen/HwModeSubRegs.td new file mode 100644 index 000000000000..2bf7a917979d --- /dev/null +++ b/llvm/test/TableGen/HwModeSubRegs.td @@ -0,0 +1,75 @@ +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s +include "llvm/Target/Target.td" + +def HasFeat : Predicate<"Subtarget->hasFeat()">; + +def TestMode : HwMode<"+feat1", [HasFeat]>; + +class MyReg + : Register { + let Namespace = "Test"; +} +class MyClass types, dag registers> + : RegisterClass<"Test", types, size, registers> { + let Size = size; +} + +def X0 : MyReg<"x0">; +def X1 : MyReg<"x1">; +def X2 : MyReg<"x2">; +def X3 : MyReg<"x3">; +def X4 : MyReg<"x4">; +def X5 : MyReg<"x5">; +def X6 : MyReg<"x6">; +def X7 : MyReg<"x7">; +def X8 : MyReg<"x8">; +def X9 : MyReg<"x9">; +def X10 : MyReg<"x10">; +def X11 : MyReg<"x11">; +def X12 : MyReg<"x12">; +def X13 : MyReg<"x13">; +def X14 : MyReg<"x14">; +def X15 : MyReg<"x15">; + +def ModeVT : ValueTypeByHwMode<[DefaultMode, TestMode], + [i32, i64]>; +let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode], + [RegInfo<32,32,32>, RegInfo<64,64,64>]> in +def XRegs : MyClass<32, [ModeVT], (sequence "X%u", 0, 15)>; + +def sub_even : SubRegIndex<32> { + let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode], + [SubRegRange<32>, SubRegRange<64>]>; +} +def sub_odd : SubRegIndex<32, 32> { + let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode], + [SubRegRange<32, 32>, SubRegRange<64, 64>]>; +} + +def XPairs : RegisterTuples<[sub_even, sub_odd], + [(decimate (rotl XRegs, 0), 2), + (decimate (rotl XRegs, 1), 2)]>; + +let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode], + [RegInfo<64,64,32>, RegInfo<128,128,64>]> in +def XPairsClass : MyClass<64, [untyped], (add XPairs)>; + +def TestTarget : Target; + +// CHECK-LABEL: RegisterClass XRegs: +// CHECK: SpillSize: { Default:32 TestMode:64 } +// CHECK: SpillAlignment: { Default:32 TestMode:64 } +// CHECK: Regs: X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + +// CHECK-LABEL: RegisterClass XPairsClass: +// CHECK: SpillSize: { Default:64 TestMode:128 } +// CHECK: SpillAlignment: { Default:32 TestMode:64 } +// CHECK: CoveredBySubRegs: 1 +// CHECK: Regs: X0_X1 X2_X3 X4_X5 X6_X7 X8_X9 X10_X11 X12_X13 X14_X15 + +// CHECK-LABEL: SubRegIndex sub_even: +// CHECK: Offset: { Default:0 TestMode:0 } +// CHECK: Size: { Default:32 TestMode:64 } +// CHECK-LABEL: SubRegIndex sub_odd: +// CHECK: Offset: { Default:32 TestMode:64 } +// CHECK: Size: { Default:32 TestMode:64 } diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp index e851d4c16bf7..624e8d5d54ba 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp @@ -47,19 +47,24 @@ using namespace llvm; // CodeGenSubRegIndex //===----------------------------------------------------------------------===// -CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) +CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum, + const CodeGenHwModes &CGH) : TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) { Name = std::string(R->getName()); if (R->getValue("Namespace")) Namespace = std::string(R->getValueAsString("Namespace")); - Size = R->getValueAsInt("Size"); - Offset = R->getValueAsInt("Offset"); + + if (const RecordVal *RV = R->getValue("SubRegRanges")) + if (auto *DI = dyn_cast_or_null(RV->getValue())) + Range = SubRegRangeByHwMode(DI->getDef(), CGH); + if (!Range.hasDefault()) + Range.insertSubRegRangeForMode(DefaultMode, SubRegRange(R)); } CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum) : TheDef(nullptr), Name(std::string(N)), Namespace(std::string(Nspace)), - Size(-1), Offset(-1), EnumValue(Enum), AllSuperRegsCovered(true), + Range(SubRegRange(-1, -1)), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {} std::string CodeGenSubRegIndex::getQualifiedName() const { @@ -81,7 +86,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { "ComposedOf must have exactly two entries"); CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); - CodeGenSubRegIndex *X = A->addComposite(B, this); + CodeGenSubRegIndex *X = A->addComposite(B, this, RegBank.getHwModes()); if (X) PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); } @@ -518,7 +523,8 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) { // Each part of Cand is a sub-register of this. Make the full Cand also // a sub-register with a concatenated sub-register index. - CodeGenSubRegIndex *Concat = RegBank.getConcatSubRegIndex(Parts); + CodeGenSubRegIndex *Concat = + RegBank.getConcatSubRegIndex(Parts, RegBank.getHwModes()); std::pair NewSubReg = std::pair(Concat, Cand); @@ -542,7 +548,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) { PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " + SubReg.second->getName() + " in " + getName()); - NewIdx->addComposite(SubReg.first, SubIdx); + NewIdx->addComposite(SubReg.first, SubIdx, RegBank.getHwModes()); } } } @@ -1315,7 +1321,7 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; if (Idx) return Idx; - SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1); + SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1, getHwModes()); Idx = &SubRegIndices.back(); return Idx; } @@ -1379,12 +1385,13 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A, // None exists, synthesize one. std::string Name = A->getName() + "_then_" + B->getName(); Comp = createSubRegIndex(Name, A->getNamespace()); - A->addComposite(B, Comp); + A->addComposite(B, Comp, getHwModes()); return Comp; } CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( - const SmallVector &Parts) { + const SmallVector &Parts, + const CodeGenHwModes &CGH) { assert(Parts.size() > 1 && "Need two parts to concatenate"); #ifndef NDEBUG for (CodeGenSubRegIndex *Idx : Parts) { @@ -1399,28 +1406,47 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( // None exists, synthesize one. std::string Name = Parts.front()->getName(); - // Determine whether all parts are contiguous. - bool IsContinuous = true; - unsigned Size = Parts.front()->Size; - unsigned LastOffset = Parts.front()->Offset; - unsigned LastSize = Parts.front()->Size; const unsigned UnknownSize = (uint16_t)-1; + for (unsigned i = 1, e = Parts.size(); i != e; ++i) { Name += '_'; Name += Parts[i]->getName(); - if (Size == UnknownSize || Parts[i]->Size == UnknownSize) - Size = UnknownSize; - else - Size += Parts[i]->Size; - if (LastSize == UnknownSize || Parts[i]->Offset != (LastOffset + LastSize)) - IsContinuous = false; - LastOffset = Parts[i]->Offset; - LastSize = Parts[i]->Size; } + Idx = createSubRegIndex(Name, Parts.front()->getNamespace()); - Idx->Size = Size; - Idx->Offset = IsContinuous ? Parts.front()->Offset : -1; Idx->ConcatenationOf.assign(Parts.begin(), Parts.end()); + + unsigned NumModes = CGH.getNumModeIds(); + for (unsigned M = 0; M < NumModes; ++M) { + const CodeGenSubRegIndex *Part = Parts.front(); + + // Determine whether all parts are contiguous. + bool IsContinuous = true; + const SubRegRange &FirstPartRange = Part->Range.get(M); + unsigned Size = FirstPartRange.Size; + unsigned LastOffset = FirstPartRange.Offset; + unsigned LastSize = FirstPartRange.Size; + + for (unsigned i = 1, e = Parts.size(); i != e; ++i) { + Part = Parts[i]; + Name += '_'; + Name += Part->getName(); + + const SubRegRange &PartRange = Part->Range.get(M); + if (Size == UnknownSize || PartRange.Size == UnknownSize) + Size = UnknownSize; + else + Size += PartRange.Size; + if (LastSize == UnknownSize || + PartRange.Offset != (LastOffset + LastSize)) + IsContinuous = false; + LastOffset = PartRange.Offset; + LastSize = PartRange.Size; + } + unsigned Offset = IsContinuous ? FirstPartRange.Offset : -1; + Idx->Range.get(M) = SubRegRange(Size, Offset); + } + return Idx; } @@ -1504,7 +1530,8 @@ void CodeGenRegBank::computeComposites() { assert(Idx3 && "Sub-register doesn't have an index"); // Conflicting composition? Emit a warning but allow it. - if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3)) { + if (CodeGenSubRegIndex *Prev = + Idx1->addComposite(Idx2, Idx3, getHwModes())) { // If the composition was not user-defined, always emit a warning. if (!UserDefined.count({Idx1, Idx2}) || agree(compose(Idx1, Idx2), SubRegAction.at(Idx3))) diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h index c34f376ea99d..9058baea2b23 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.h +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h @@ -68,8 +68,7 @@ class CodeGenSubRegIndex { std::string Namespace; public: - uint16_t Size; - uint16_t Offset; + SubRegRangeByHwMode Range; const unsigned EnumValue; mutable LaneBitmask LaneMask; mutable SmallVector CompositionLaneMaskTransform; @@ -86,7 +85,7 @@ public: // indexes are not used to create new register classes. bool Artificial; - CodeGenSubRegIndex(Record *R, unsigned Enum); + CodeGenSubRegIndex(Record *R, unsigned Enum, const CodeGenHwModes &CGH); CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum); CodeGenSubRegIndex(CodeGenSubRegIndex &) = delete; @@ -108,19 +107,42 @@ public: // Add a composite subreg index: this+A = B. // Return a conflicting composite, or NULL - CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, - CodeGenSubRegIndex *B) { + CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B, + const CodeGenHwModes &CGH) { assert(A && B); std::pair Ins = Composed.insert(std::pair(A, B)); + // Synthetic subreg indices that aren't contiguous (for instance ARM // register tuples) don't have a bit range, so it's OK to let // B->Offset == -1. For the other cases, accumulate the offset and set // the size here. Only do so if there is no offset yet though. - if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) && - (B->Offset == (uint16_t)-1)) { - B->Offset = Offset + A->Offset; - B->Size = A->Size; + unsigned NumModes = CGH.getNumModeIds(); + // Skip default mode. + for (unsigned M = 0; M < NumModes; ++M) { + // Handle DefaultMode last. + if (M == DefaultMode) + continue; + SubRegRange &Range = this->Range.get(M); + SubRegRange &ARange = A->Range.get(M); + SubRegRange &BRange = B->Range.get(M); + + if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 && + BRange.Offset == (uint16_t)-1) { + BRange.Offset = Range.Offset + ARange.Offset; + BRange.Size = ARange.Size; + } + } + + // Now handle default. + SubRegRange &Range = this->Range.get(DefaultMode); + SubRegRange &ARange = A->Range.get(DefaultMode); + SubRegRange &BRange = B->Range.get(DefaultMode); + if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 && + BRange.Offset == (uint16_t)-1) { + BRange.Offset = Range.Offset + ARange.Offset; + BRange.Size = ARange.Size; } + return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second; } @@ -681,7 +703,8 @@ public: // Find or create a sub-register index representing the concatenation of // non-overlapping sibling indices. CodeGenSubRegIndex * - getConcatSubRegIndex(const SmallVector &); + getConcatSubRegIndex(const SmallVector &, + const CodeGenHwModes &CGH); const std::deque &getRegisters() const { return Registers; } diff --git a/llvm/utils/TableGen/Common/InfoByHwMode.cpp b/llvm/utils/TableGen/Common/InfoByHwMode.cpp index 5496408bb0d3..cacf4ece6671 100644 --- a/llvm/utils/TableGen/Common/InfoByHwMode.cpp +++ b/llvm/utils/TableGen/Common/InfoByHwMode.cpp @@ -183,6 +183,20 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const { OS << '}'; } +SubRegRange::SubRegRange(Record *R) { + Size = R->getValueAsInt("Size"); + Offset = R->getValueAsInt("Offset"); +} + +SubRegRangeByHwMode::SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH) { + const HwModeSelect &MS = CGH.getHwModeSelect(R); + for (const HwModeSelect::PairType &P : MS.Items) { + auto I = Map.insert({P.first, SubRegRange(P.second)}); + assert(I.second && "Duplicate entry?"); + (void)I; + } +} + EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH) { const HwModeSelect &MS = CGH.getHwModeSelect(R); diff --git a/llvm/utils/TableGen/Common/InfoByHwMode.h b/llvm/utils/TableGen/Common/InfoByHwMode.h index 1909913c50c6..dd0b9830d757 100644 --- a/llvm/utils/TableGen/Common/InfoByHwMode.h +++ b/llvm/utils/TableGen/Common/InfoByHwMode.h @@ -176,6 +176,8 @@ struct ValueTypeByHwMode : public InfoByHwMode { ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH); +raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); + struct RegSizeInfo { unsigned RegSize; unsigned SpillSize; @@ -213,10 +215,27 @@ struct RegSizeInfoByHwMode : public InfoByHwMode { } }; -raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T); +struct SubRegRange { + uint16_t Size; + uint16_t Offset; + + SubRegRange(Record *R); + SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {} +}; + +struct SubRegRangeByHwMode : public InfoByHwMode { + SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH); + SubRegRangeByHwMode(SubRegRange Range) { Map.insert({DefaultMode, Range}); } + SubRegRangeByHwMode() = default; + + void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) { + Map.insert(std::pair(Mode, Info)); + } +}; + struct EncodingInfoByHwMode : public InfoByHwMode { EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH); EncodingInfoByHwMode() = default; diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp index a1259bff6ba8..ee8830edeedb 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -1245,10 +1245,13 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the table of sub-register index sizes. OS << "static const TargetRegisterInfo::SubRegCoveredBits " "SubRegIdxRangeTable[] = {\n"; - OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; - for (const auto &Idx : SubRegIndices) { - OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " - << Idx.getName() << "\n"; + for (unsigned M = 0; M < NumModes; ++M) { + OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; + for (const auto &Idx : SubRegIndices) { + const SubRegRange &Range = Idx.Range.get(M); + OS << " { " << Range.Offset << ", " << Range.Size << " },\t// " + << Idx.getName() << "\n"; + } } OS << "};\n\n"; @@ -1864,7 +1867,13 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) { OS << "SubRegIndex " << SRI.getName() << ":\n"; OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n'; OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n'; - OS << "\tOffset, Size: " << SRI.Offset << ", " << SRI.Size << '\n'; + OS << "\tOffset: {"; + for (unsigned M = 0; M != NumModes; ++M) + OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Offset; + OS << " }\n\tSize: {"; + for (unsigned M = 0; M != NumModes; ++M) + OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Size; + OS << " }\n"; } for (const CodeGenRegister &R : RegBank.getRegisters()) { -- GitLab From 10bd55566a01c63d9e4f46da5a4e671684aa7fc5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Mar 2024 12:20:24 -0700 Subject: [PATCH 107/541] [RISCV] Model vd as a src for some Zvk* instructions in MC layer. (#86710) Some Zvk instructions use vd as a source regardless of tail policy. Model this in the MC layer. We already do this for FMA for example. --- llvm/lib/Target/RISCV/RISCVInstrInfoV.td | 8 ---- llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td | 52 ++++++++++++++++------ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td index 875f2e382d54..e68fb42ece9f 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td @@ -531,14 +531,6 @@ class VALUVs2 funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> : RVInstV; - -// op vd, vs2 (use vs1 as instruction encoding) -class VALUVs2NoVm funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> - : RVInstV { - let vm = 1; -} } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td index b388bb00b0f2..60db03d68e47 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td @@ -67,6 +67,16 @@ class PALUVVNoVm funct6, RISCVVFormat opv, string opcodestr> let Inst{6-0} = OPC_OP_P.Value; } +// op vd, vs2, vs1 +class PALUVVNoVmTernary funct6, RISCVVFormat opv, string opcodestr> + : RVInstVV { + let Constraints = "$vd = $vd_wb"; + let vm = 1; + let Inst{6-0} = OPC_OP_P.Value; +} + // op vd, vs2, imm class PALUVINoVm funct6, string opcodestr, Operand optype> : VALUVINoVm { @@ -74,18 +84,34 @@ class PALUVINoVm funct6, string opcodestr, Operand optype> let Inst{14-12} = OPMVV.Value; } -// op vd, vs2 (use vs1 as instruction encoding) -class PALUVs2NoVm funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> - : VALUVs2NoVm { +// op vd, vs2, imm where vd is also a source regardless of tail policy +class PALUVINoVmBinary funct6, string opcodestr, Operand optype> + : RVInstIVI { + let Constraints = "$vd = $vd_wb"; + let vm = 1; + let Inst{6-0} = OPC_OP_P.Value; + let Inst{14-12} = OPMVV.Value; +} + +// op vd, vs2 (use vs1 as instruction encoding) where vd is also a source +// regardless of tail policy +class PALUVs2NoVmBinary funct6, bits<5> vs1, RISCVVFormat opv, + string opcodestr> + : RVInstV { + let Constraints = "$vd = $vd_wb"; + let vm = 1; let Inst{6-0} = OPC_OP_P.Value; } multiclass VAES_MV_V_S funct6_vv, bits<6> funct6_vs, bits<5> vs1, RISCVVFormat opv, string opcodestr> { let RVVConstraint = NoConstraint in - def NAME # _VV : PALUVs2NoVm; + def NAME # _VV : PALUVs2NoVmBinary; let RVVConstraint = VS2Constraint in - def NAME # _VS : PALUVs2NoVm; + def NAME # _VS : PALUVs2NoVmBinary; } } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 @@ -116,14 +142,14 @@ let Predicates = [HasStdExtZvkb] in { } // Predicates = [HasStdExtZvkb] let Predicates = [HasStdExtZvkg], RVVConstraint = NoConstraint in { - def VGHSH_VV : PALUVVNoVm<0b101100, OPMVV, "vghsh.vv">; - def VGMUL_VV : PALUVs2NoVm<0b101000, 0b10001, OPMVV, "vgmul.vv">; + def VGHSH_VV : PALUVVNoVmTernary<0b101100, OPMVV, "vghsh.vv">; + def VGMUL_VV : PALUVs2NoVmBinary<0b101000, 0b10001, OPMVV, "vgmul.vv">; } // Predicates = [HasStdExtZvkg] let Predicates = [HasStdExtZvknhaOrZvknhb], RVVConstraint = Sha2Constraint in { - def VSHA2CH_VV : PALUVVNoVm<0b101110, OPMVV, "vsha2ch.vv">; - def VSHA2CL_VV : PALUVVNoVm<0b101111, OPMVV, "vsha2cl.vv">; - def VSHA2MS_VV : PALUVVNoVm<0b101101, OPMVV, "vsha2ms.vv">; + def VSHA2CH_VV : PALUVVNoVmTernary<0b101110, OPMVV, "vsha2ch.vv">; + def VSHA2CL_VV : PALUVVNoVmTernary<0b101111, OPMVV, "vsha2cl.vv">; + def VSHA2MS_VV : PALUVVNoVmTernary<0b101101, OPMVV, "vsha2ms.vv">; } // Predicates = [HasStdExtZvknhaOrZvknhb] let Predicates = [HasStdExtZvkned]in { @@ -132,9 +158,9 @@ let Predicates = [HasStdExtZvkned]in { defm VAESEF : VAES_MV_V_S<0b101000, 0b101001, 0b00011, OPMVV, "vaesef">; defm VAESEM : VAES_MV_V_S<0b101000, 0b101001, 0b00010, OPMVV, "vaesem">; def VAESKF1_VI : PALUVINoVm<0b100010, "vaeskf1.vi", uimm5>; - def VAESKF2_VI : PALUVINoVm<0b101010, "vaeskf2.vi", uimm5>; + def VAESKF2_VI : PALUVINoVmBinary<0b101010, "vaeskf2.vi", uimm5>; let RVVConstraint = VS2Constraint in - def VAESZ_VS : PALUVs2NoVm<0b101001, 0b00111, OPMVV, "vaesz.vs">; + def VAESZ_VS : PALUVs2NoVmBinary<0b101001, 0b00111, OPMVV, "vaesz.vs">; } // Predicates = [HasStdExtZvkned] let Predicates = [HasStdExtZvksed] in { @@ -144,7 +170,7 @@ let Predicates = [HasStdExtZvksed] in { } // Predicates = [HasStdExtZvksed] let Predicates = [HasStdExtZvksh], RVVConstraint = VS2Constraint in { - def VSM3C_VI : PALUVINoVm<0b101011, "vsm3c.vi", uimm5>; + def VSM3C_VI : PALUVINoVmBinary<0b101011, "vsm3c.vi", uimm5>; def VSM3ME_VV : PALUVVNoVm<0b100000, OPMVV, "vsm3me.vv">; } // Predicates = [HasStdExtZvksh] -- GitLab From d9a685a9dd589486e882b722e513ee7b8c84870c Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 27 Mar 2024 12:24:49 -0700 Subject: [PATCH 108/541] [CodeGen][arm64e] Add methods and data members to Address, which are needed to authenticate signed pointers (#86721) To authenticate pointers, CodeGen needs access to the key and discriminators that were used to sign the pointer. That information is sometimes known from the context, but not always, which is why `Address` needs to hold that information. This patch adds methods and data members to `Address`, which will be needed in subsequent patches to authenticate signed pointers, and uses the newly added methods throughout CodeGen. Although this patch isn't strictly NFC as it causes CodeGen to use different code paths in some cases (e.g., `mergeAddressesInConditionalExpr`), it doesn't cause any changes in functionality as it doesn't add any information needed for authentication. In addition to the changes mentioned above, this patch introduces class `RawAddress`, which contains a pointer that we know is unsigned, and adds several new functions for creating `Address` and `LValue` objects. This reapplies 8bd1f9116aab879183f34707e6d21c7051d083b6. The commit broke msan bots because LValue::IsKnownNonNull was uninitialized. --- clang/lib/CodeGen/ABIInfoImpl.cpp | 10 +- clang/lib/CodeGen/Address.h | 195 ++++++++++++++--- clang/lib/CodeGen/CGAtomic.cpp | 53 ++--- clang/lib/CodeGen/CGBlocks.cpp | 34 +-- clang/lib/CodeGen/CGBlocks.h | 3 +- clang/lib/CodeGen/CGBuilder.h | 234 ++++++++++++++------- clang/lib/CodeGen/CGBuiltin.cpp | 173 +++++++-------- clang/lib/CodeGen/CGCUDANV.cpp | 19 +- clang/lib/CodeGen/CGCXXABI.cpp | 21 +- clang/lib/CodeGen/CGCXXABI.h | 14 +- clang/lib/CodeGen/CGCall.cpp | 171 ++++++++------- clang/lib/CodeGen/CGCall.h | 1 + clang/lib/CodeGen/CGClass.cpp | 76 ++++--- clang/lib/CodeGen/CGCleanup.cpp | 110 ++++------ clang/lib/CodeGen/CGCleanup.h | 2 +- clang/lib/CodeGen/CGCoroutine.cpp | 4 +- clang/lib/CodeGen/CGDecl.cpp | 28 +-- clang/lib/CodeGen/CGException.cpp | 19 +- clang/lib/CodeGen/CGExpr.cpp | 227 ++++++++++---------- clang/lib/CodeGen/CGExprAgg.cpp | 29 +-- clang/lib/CodeGen/CGExprCXX.cpp | 111 +++++----- clang/lib/CodeGen/CGExprConstant.cpp | 4 +- clang/lib/CodeGen/CGExprScalar.cpp | 23 +- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 8 +- clang/lib/CodeGen/CGObjC.cpp | 43 ++-- clang/lib/CodeGen/CGObjCGNU.cpp | 42 ++-- clang/lib/CodeGen/CGObjCMac.cpp | 95 ++++----- clang/lib/CodeGen/CGObjCRuntime.cpp | 6 +- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 194 +++++++++-------- clang/lib/CodeGen/CGOpenMPRuntime.h | 5 +- clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 76 +++---- clang/lib/CodeGen/CGStmt.cpp | 8 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 87 ++++---- clang/lib/CodeGen/CGVTables.cpp | 9 +- clang/lib/CodeGen/CGValue.h | 250 +++++++++++----------- clang/lib/CodeGen/CodeGenFunction.cpp | 71 ++++--- clang/lib/CodeGen/CodeGenFunction.h | 257 ++++++++++++++++------- clang/lib/CodeGen/CodeGenModule.cpp | 2 +- clang/lib/CodeGen/CodeGenPGO.cpp | 10 +- clang/lib/CodeGen/CodeGenPGO.h | 6 +- clang/lib/CodeGen/ItaniumCXXABI.cpp | 52 ++--- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 58 ++--- clang/lib/CodeGen/TargetInfo.h | 5 + clang/lib/CodeGen/Targets/NVPTX.cpp | 2 +- clang/lib/CodeGen/Targets/PPC.cpp | 11 +- clang/lib/CodeGen/Targets/Sparc.cpp | 2 +- clang/lib/CodeGen/Targets/SystemZ.cpp | 9 +- clang/lib/CodeGen/Targets/XCore.cpp | 2 +- clang/utils/TableGen/MveEmitter.cpp | 2 +- llvm/include/llvm/IR/IRBuilder.h | 1 + 50 files changed, 1640 insertions(+), 1234 deletions(-) diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index dd59101ecc81..3e34d82cb399 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -187,7 +187,7 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits FullDirectSize = DirectSize.alignTo(SlotSize); Address NextPtr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next"); - CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); // If the argument is smaller than a slot, and this is a big-endian // target, the argument will be right-adjusted in its slot. @@ -239,8 +239,8 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, const llvm::Twine &Name) { assert(Addr1.getType() == Addr2.getType()); llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name); - PHI->addIncoming(Addr1.getPointer(), Block1); - PHI->addIncoming(Addr2.getPointer(), Block2); + PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1); + PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2); CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment()); return Address(PHI, Addr1.getElementType(), Align); } @@ -400,7 +400,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty); llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy); llvm::Value *Addr = - CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy); + CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy); return Address(Addr, ElementTy, TyAlignForABI); } else { assert((AI.isDirect() || AI.isExtend()) && @@ -416,7 +416,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!"); Address Temp = CGF.CreateMemTemp(Ty, "varet"); - Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(), + Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Ty)); CGF.Builder.CreateStore(Val, Temp); return Temp; diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index cf48df8f5e73..35ec370a139c 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #include "clang/AST/CharUnits.h" +#include "clang/AST/Type.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Constants.h" #include "llvm/Support/MathExtras.h" @@ -22,28 +23,41 @@ namespace clang { namespace CodeGen { +class Address; +class CGBuilderTy; +class CodeGenFunction; +class CodeGenModule; + // Indicates whether a pointer is known not to be null. enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; -/// An aligned address. -class Address { +/// An abstract representation of an aligned address. This is designed to be an +/// IR-level abstraction, carrying just the information necessary to perform IR +/// operations on an address like loads and stores. In particular, it doesn't +/// carry C type information or allow the representation of things like +/// bit-fields; clients working at that level should generally be using +/// `LValue`. +/// The pointer contained in this class is known to be unsigned. +class RawAddress { llvm::PointerIntPair PointerAndKnownNonNull; llvm::Type *ElementType; CharUnits Alignment; protected: - Address(std::nullptr_t) : ElementType(nullptr) {} + RawAddress(std::nullptr_t) : ElementType(nullptr) {} public: - Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, - KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) : PointerAndKnownNonNull(Pointer, IsKnownNonNull), ElementType(ElementType), Alignment(Alignment) { assert(Pointer != nullptr && "Pointer cannot be null"); assert(ElementType != nullptr && "Element type cannot be null"); } - static Address invalid() { return Address(nullptr); } + inline RawAddress(Address Addr); + + static RawAddress invalid() { return RawAddress(nullptr); } bool isValid() const { return PointerAndKnownNonNull.getPointer() != nullptr; } @@ -80,6 +94,133 @@ public: return Alignment; } + /// Return address with different element type, but same pointer and + /// alignment. + RawAddress withElementType(llvm::Type *ElemTy) const { + return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); + } + + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); + } +}; + +/// Like RawAddress, an abstract representation of an aligned address, but the +/// pointer contained in this class is possibly signed. +class Address { + friend class CGBuilderTy; + + // The boolean flag indicates whether the pointer is known to be non-null. + llvm::PointerIntPair Pointer; + + /// The expected IR type of the pointer. Carrying accurate element type + /// information in Address makes it more convenient to work with Address + /// values and allows frontend assertions to catch simple mistakes. + llvm::Type *ElementType = nullptr; + + CharUnits Alignment; + + /// Offset from the base pointer. + llvm::Value *Offset = nullptr; + + llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const; + +protected: + Address(std::nullptr_t) : ElementType(nullptr) {} + +public: + Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(pointer, IsKnownNonNull), ElementType(elementType), + Alignment(alignment) { + assert(pointer != nullptr && "Pointer cannot be null"); + assert(elementType != nullptr && "Element type cannot be null"); + assert(!alignment.isZero() && "Alignment cannot be zero"); + } + + Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment, + llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType), + Alignment(Alignment), Offset(Offset) {} + + Address(RawAddress RawAddr) + : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr), + ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr), + Alignment(RawAddr.isValid() ? RawAddr.getAlignment() + : CharUnits::Zero()) {} + + static Address invalid() { return Address(nullptr); } + bool isValid() const { return Pointer.getPointer() != nullptr; } + + /// This function is used in situations where the caller is doing some sort of + /// opaque "laundering" of the pointer. + void replaceBasePointer(llvm::Value *P) { + assert(isValid() && "pointer isn't valid"); + assert(P->getType() == Pointer.getPointer()->getType() && + "Pointer's type changed"); + Pointer.setPointer(P); + assert(isValid() && "pointer is invalid after replacement"); + } + + CharUnits getAlignment() const { return Alignment; } + + void setAlignment(CharUnits Value) { Alignment = Value; } + + llvm::Value *getBasePointer() const { + assert(isValid() && "pointer isn't valid"); + return Pointer.getPointer(); + } + + /// Return the type of the pointer value. + llvm::PointerType *getType() const { + return llvm::PointerType::get( + ElementType, + llvm::cast(Pointer.getPointer()->getType()) + ->getAddressSpace()); + } + + /// Return the type of the values stored in this address. + llvm::Type *getElementType() const { + assert(isValid()); + return ElementType; + } + + /// Return the address space that this address resides in. + unsigned getAddressSpace() const { return getType()->getAddressSpace(); } + + /// Return the IR name of the pointer value. + llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } + + // This function is called only in CGBuilderBaseTy::CreateElementBitCast. + void setElementType(llvm::Type *Ty) { + assert(hasOffset() && + "this funcion shouldn't be called when there is no offset"); + ElementType = Ty; + } + + /// Whether the pointer is known not to be null. + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)Pointer.getInt(); + } + + Address setKnownNonNull() { + assert(isValid()); + Pointer.setInt(KnownNonNull); + return *this; + } + + bool hasOffset() const { return Offset; } + + llvm::Value *getOffset() const { return Offset; } + + /// Return the pointer contained in this class after authenticating it and + /// adding offset to it if necessary. + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return getBasePointer(); + } + /// Return address with different pointer, but same element type and /// alignment. Address withPointer(llvm::Value *NewPointer, @@ -91,61 +232,59 @@ public: /// Return address with different alignment, but same pointer and element /// type. Address withAlignment(CharUnits NewAlignment) const { - return Address(getPointer(), getElementType(), NewAlignment, + return Address(Pointer.getPointer(), getElementType(), NewAlignment, isKnownNonNull()); } /// Return address with different element type, but same pointer and /// alignment. Address withElementType(llvm::Type *ElemTy) const { - return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); - } - - /// Whether the pointer is known not to be null. - KnownNonNull_t isKnownNonNull() const { - assert(isValid()); - return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); - } - - /// Set the non-null bit. - Address setKnownNonNull() { - assert(isValid()); - PointerAndKnownNonNull.setInt(true); - return *this; + if (!hasOffset()) + return Address(getBasePointer(), ElemTy, getAlignment(), nullptr, + isKnownNonNull()); + Address A(*this); + A.ElementType = ElemTy; + return A; } }; +inline RawAddress::RawAddress(Address Addr) + : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, + Addr.isValid() ? Addr.isKnownNonNull() + : NotKnownNonNull), + ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), + Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} + /// A specialization of Address that requires the address to be an /// LLVM Constant. -class ConstantAddress : public Address { - ConstantAddress(std::nullptr_t) : Address(nullptr) {} +class ConstantAddress : public RawAddress { + ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {} public: ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, CharUnits alignment) - : Address(pointer, elementType, alignment) {} + : RawAddress(pointer, elementType, alignment) {} static ConstantAddress invalid() { return ConstantAddress(nullptr); } llvm::Constant *getPointer() const { - return llvm::cast(Address::getPointer()); + return llvm::cast(RawAddress::getPointer()); } ConstantAddress withElementType(llvm::Type *ElemTy) const { return ConstantAddress(getPointer(), ElemTy, getAlignment()); } - static bool isaImpl(Address addr) { + static bool isaImpl(RawAddress addr) { return llvm::isa(addr.getPointer()); } - static ConstantAddress castImpl(Address addr) { + static ConstantAddress castImpl(RawAddress addr) { return ConstantAddress(llvm::cast(addr.getPointer()), addr.getElementType(), addr.getAlignment()); } }; - } // Present a minimal LLVM-like casting interface. diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index fb03d013e8af..56198385de9d 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -80,7 +80,7 @@ namespace { AtomicSizeInBits = C.toBits( C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1) .alignTo(lvalue.getAlignment())); - llvm::Value *BitFieldPtr = lvalue.getBitFieldPointer(); + llvm::Value *BitFieldPtr = lvalue.getRawBitFieldPointer(CGF); auto OffsetInChars = (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) * lvalue.getAlignment(); @@ -139,13 +139,13 @@ namespace { const LValue &getAtomicLValue() const { return LVal; } llvm::Value *getAtomicPointer() const { if (LVal.isSimple()) - return LVal.getPointer(CGF); + return LVal.emitRawPointer(CGF); else if (LVal.isBitField()) - return LVal.getBitFieldPointer(); + return LVal.getRawBitFieldPointer(CGF); else if (LVal.isVectorElt()) - return LVal.getVectorPointer(); + return LVal.getRawVectorPointer(CGF); assert(LVal.isExtVectorElt()); - return LVal.getExtVectorPointer(); + return LVal.getRawExtVectorPointer(CGF); } Address getAtomicAddress() const { llvm::Type *ElTy; @@ -368,7 +368,7 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const { return false; CGF.Builder.CreateMemSet( - addr.getPointer(), llvm::ConstantInt::get(CGF.Int8Ty, 0), + addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0), CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(), LVal.getAlignment().getAsAlign()); return true; @@ -1055,7 +1055,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { return getTargetHooks().performAddrSpaceCast( *this, V, AS, LangAS::opencl_generic, DestType, false); }; - Args.add(RValue::get(CastToGenericAddrSpace(Ptr.getPointer(), + + Args.add(RValue::get(CastToGenericAddrSpace(Ptr.emitRawPointer(*this), E->getPtr()->getType())), getContext().VoidPtrTy); @@ -1086,10 +1087,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_compare_exchange"; RetTy = getContext().BoolTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); - Args.add(RValue::get(CastToGenericAddrSpace(Val2.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val2.emitRawPointer(*this), E->getVal2()->getType())), getContext().VoidPtrTy); Args.add(RValue::get(Order), getContext().IntTy); @@ -1105,7 +1106,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__scoped_atomic_exchange: case AtomicExpr::AO__scoped_atomic_exchange_n: LibCallName = "__atomic_exchange"; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1120,7 +1121,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_store"; RetTy = getContext().VoidTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1199,7 +1200,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { if (!HaveRetTy) { // Value is returned through parameter before the order. RetTy = getContext().VoidTy; - Args.add(RValue::get(CastToGenericAddrSpace(Dest.getPointer(), RetTy)), + Args.add(RValue::get( + CastToGenericAddrSpace(Dest.emitRawPointer(*this), RetTy)), getContext().VoidPtrTy); } // Order is always the last parameter. @@ -1513,7 +1515,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } else TempAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(TempAddr.emitRawPointer(CGF), AO, IsVolatile); // Okay, turn that back into the original value or whole atomic (for // non-simple lvalues) type. @@ -1673,9 +1675,9 @@ std::pair AtomicInfo::EmitAtomicCompareExchange( if (shouldUseLibcall()) { // Produce a source address. Address ExpectedAddr = materializeRValue(Expected); - Address DesiredAddr = materializeRValue(Desired); - auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF); + auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, Success, Failure); return std::make_pair( convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(), @@ -1757,7 +1759,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall( Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1771,10 +1773,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall( AggValueSlot::ignored(), SourceLocation(), /*AsValue=*/false); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1843,7 +1845,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1854,10 +1856,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, CGF.Builder.CreateStore(OldVal, DesiredAddr); } EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1957,7 +1959,8 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(atomics.getAtomicPointer()), getContext().VoidPtrTy); - args.add(RValue::get(srcAddr.getPointer()), getContext().VoidPtrTy); + args.add(RValue::get(srcAddr.emitRawPointer(*this)), + getContext().VoidPtrTy); args.add( RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))), getContext().IntTy); diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index ad0b50d79961..a01f2c7c9798 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -36,7 +36,8 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), NoEscape(false), HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), CapturesNonExternalType(false), - LocalAddress(Address::invalid()), StructureType(nullptr), Block(block) { + LocalAddress(RawAddress::invalid()), StructureType(nullptr), + Block(block) { // Skip asm prefix, if any. 'name' is usually taken directly from // the mangled name of the enclosing function. @@ -794,7 +795,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // Otherwise, we have to emit this as a local block. - Address blockAddr = blockInfo.LocalAddress; + RawAddress blockAddr = blockInfo.LocalAddress; assert(blockAddr.isValid() && "block has no address!"); llvm::Constant *isa; @@ -939,7 +940,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { if (CI.isNested()) byrefPointer = Builder.CreateLoad(src, "byref.capture"); else - byrefPointer = src.getPointer(); + byrefPointer = src.emitRawPointer(*this); // Write that void* into the capture field. Builder.CreateStore(byrefPointer, blockField); @@ -961,10 +962,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { } // If it's a reference variable, copy the reference into the block field. - } else if (type->isReferenceType()) { - Builder.CreateStore(src.getPointer(), blockField); + } else if (auto refType = type->getAs()) { + Builder.CreateStore(src.emitRawPointer(*this), blockField); - // If type is const-qualified, copy the value into the block field. + // If type is const-qualified, copy the value into the block field. } else if (type.isConstQualified() && type.getObjCLifetime() == Qualifiers::OCL_Strong && CGM.getCodeGenOpts().OptimizationLevel != 0) { @@ -1377,7 +1378,7 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, // Allocate a stack slot like for any local variable to guarantee optimal // debug info at -O0. The mem2reg pass will eliminate it when optimizing. - Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); + RawAddress alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); Builder.CreateStore(arg, alloc); if (CGDebugInfo *DI = getDebugInfo()) { if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { @@ -1497,7 +1498,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( // frame setup instruction by llvm::DwarfDebug::beginFunction(). auto NL = ApplyDebugLocation::CreateEmpty(*this); Builder.CreateStore(BlockPointer, Alloca); - BlockPointerDbgLoc = Alloca.getPointer(); + BlockPointerDbgLoc = Alloca.emitRawPointer(*this); } // If we have a C++ 'this' reference, go ahead and force it into @@ -1557,8 +1558,8 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); if (capture.isConstant()) { auto addr = LocalDeclMap.find(variable)->second; - (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), - Builder); + (void)DI->EmitDeclareOfAutoVariable( + variable, addr.emitRawPointer(*this), Builder); continue; } @@ -1662,7 +1663,7 @@ struct CallBlockRelease final : EHScopeStack::Cleanup { if (LoadBlockVarAddr) { BlockVarAddr = CGF.Builder.CreateLoad(Addr); } else { - BlockVarAddr = Addr.getPointer(); + BlockVarAddr = Addr.emitRawPointer(CGF); } CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow); @@ -1962,13 +1963,15 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - cast(dstField.getPointer())->eraseFromParent(); + if (auto *I = + cast_or_null(dstField.getBasePointer())) + I->eraseFromParent(); } break; } case BlockCaptureEntityKind::BlockObject: { llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - llvm::Value *dstAddr = dstField.getPointer(); + llvm::Value *dstAddr = dstField.emitRawPointer(*this); llvm::Value *args[] = { dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) }; @@ -2139,7 +2142,7 @@ public: llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign(); - llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal }; + llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2696,7 +2699,8 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { storeHeaderField(V, getPointerSize(), "byref.isa"); // Store the address of the variable into its own forwarding pointer. - storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding"); + storeHeaderField(addr.emitRawPointer(*this), getPointerSize(), + "byref.forwarding"); // Blocks ABI: // c) the flags field is set to either 0 if no helper functions are diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index 4ef1ae9f3365..8d10c4f69b20 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -271,7 +271,8 @@ public: /// The block's captures. Non-constant captures are sorted by their offsets. llvm::SmallVector SortedCaptures; - Address LocalAddress; + // Currently we assume that block-pointer types are never signed. + RawAddress LocalAddress; llvm::StructType *StructureType; const BlockDecl *Block; const BlockExpr *BlockExpression; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index bf5ab171d720..6dd9da7c4cad 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -10,7 +10,9 @@ #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #include "Address.h" +#include "CGValue.h" #include "CodeGenTypeCache.h" +#include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Type.h" @@ -18,12 +20,15 @@ namespace clang { namespace CodeGen { +class CGBuilderTy; class CodeGenFunction; /// This is an IRBuilder insertion helper that forwards to /// CodeGenFunction::InsertHelper, which adds necessary metadata to /// instructions. class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { + friend CGBuilderTy; + public: CGBuilderInserter() = default; explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} @@ -43,10 +48,42 @@ typedef llvm::IRBuilder CGBuilderBaseTy; class CGBuilderTy : public CGBuilderBaseTy { + friend class Address; + /// Storing a reference to the type cache here makes it a lot easier /// to build natural-feeling, target-specific IR. const CodeGenTypeCache &TypeCache; + CodeGenFunction *getCGF() const { return getInserter().CGF; } + + llvm::Value *emitRawPointerFromAddress(Address Addr) const { + return Addr.getBasePointer(); + } + + template + Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name) { + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + llvm::GetElementPtrInst *GEP; + if (IsInBounds) + GEP = cast(CreateConstInBoundsGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + else + GEP = cast(CreateConstGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + llvm::APInt Offset( + DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, + /*isSigned=*/true); + if (!GEP->accumulateConstantOffset(DL, Offset)) + llvm_unreachable("offset of GEP with constants is always computable"); + return Address(GEP, GEP->getResultElementType(), + Addr.getAlignment().alignmentAtOffset( + CharUnits::fromQuantity(Offset.getSExtValue())), + IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull); + } + public: CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) : CGBuilderBaseTy(C), TypeCache(TypeCache) {} @@ -69,20 +106,22 @@ public: // Note that we intentionally hide the CreateLoad APIs that don't // take an alignment. llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { // This overload is required to prevent string literals from // ending up in the IsVolatile overload. - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), - Addr.getAlignment().getAsAlign(), IsVolatile, - Name); + return CreateAlignedLoad( + Addr.getElementType(), emitRawPointerFromAddress(Addr), + Addr.getAlignment().getAsAlign(), IsVolatile, Name); } using CGBuilderBaseTy::CreateAlignedLoad; @@ -96,7 +135,7 @@ public: // take an alignment. llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile = false) { - return CreateAlignedStore(Val, Addr.getPointer(), + return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), IsVolatile); } @@ -132,33 +171,41 @@ public: llvm::AtomicOrdering FailureOrdering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { return CGBuilderBaseTy::CreateAtomicCmpXchg( - Addr.getPointer(), Cmp, New, Addr.getAlignment().getAsAlign(), - SuccessOrdering, FailureOrdering, SSID); + Addr.emitRawPointer(*getCGF()), Cmp, New, + Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering, + SSID); } llvm::AtomicRMWInst * CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Ordering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { - return CGBuilderBaseTy::CreateAtomicRMW(Op, Addr.getPointer(), Val, - Addr.getAlignment().getAsAlign(), - Ordering, SSID); + return CGBuilderBaseTy::CreateAtomicRMW( + Op, Addr.emitRawPointer(*getCGF()), Val, + Addr.getAlignment().getAsAlign(), Ordering, SSID); } using CGBuilderBaseTy::CreateAddrSpaceCast; Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, + llvm::Type *ElementTy, const llvm::Twine &Name = "") { - return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), - Addr.isKnownNonNull()); + if (!Addr.hasOffset()) + return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), + ElementTy, Addr.getAlignment(), nullptr, + Addr.isKnownNonNull()); + // Eagerly force a raw address if these is an offset. + return RawAddress( + CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), + ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); } using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name = "") { - llvm::Value *Ptr = - CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); - return Address(Ptr, ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); + if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace()) + return Addr.withElementType(ElementTy); + return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name); } /// Given @@ -176,10 +223,11 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address( - CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); + return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), + Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } /// Given @@ -198,7 +246,7 @@ public: CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), {getSize(CharUnits::Zero()), getSize(Index)}, Name), ElTy->getElementType(), Addr.getAlignment().alignmentAtOffset(Index * EltSize), @@ -216,10 +264,10 @@ public: const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -229,110 +277,133 @@ public: /// where i64 is actually the target word size. Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name = "") { + llvm::Type *ElTy = Addr.getElementType(); const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - CharUnits EltSize = - CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); + CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), + return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); } /// Create GEP with single dynamic index. The address alignment is reduced /// according to the element size. using CGBuilderBaseTy::CreateGEP; - Address CreateGEP(Address Addr, llvm::Value *Index, + Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name = "") { const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); return Address( - CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name), Addr.getElementType(), - Addr.getAlignment().alignmentOfArrayElement(EltSize), NotKnownNonNull); + Addr.getAlignment().alignmentOfArrayElement(EltSize)); } /// Given a pointer to i8, adjust it by a given constant offset. Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Offset), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + getSize(Offset), Name), + Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } + Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), getSize(Offset), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Offset)); } using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name = "") { - const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + return createConstGEP2_32(Addr, Idx0, Idx1, Name); + } - auto *GEP = cast(CreateConstInBoundsGEP2_32( - Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); - llvm::APInt Offset( - DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, - /*isSigned=*/true); - if (!GEP->accumulateConstantOffset(DL, Offset)) - llvm_unreachable("offset of GEP with constants is always computable"); - return Address(GEP, GEP->getResultElementType(), - Addr.getAlignment().alignmentAtOffset( - CharUnits::fromQuantity(Offset.getSExtValue())), - Addr.isKnownNonNull()); + using CGBuilderBaseTy::CreateConstGEP2_32; + Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name = "") { + return createConstGEP2_32(Addr, Idx0, Idx1, Name); + } + + Address CreateGEP(Address Addr, ArrayRef IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + llvm::Value *Ptr = emitRawPointerFromAddress(Addr); + return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name), + ElementType, Align); + } + + using CGBuilderBaseTy::CreateInBoundsGEP; + Address CreateInBoundsGEP(Address Addr, ArrayRef IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + return RawAddress(CreateInBoundsGEP(Addr.getElementType(), + emitRawPointerFromAddress(Addr), + IdxList, Name), + ElementType, Align, Addr.isKnownNonNull()); + } + + using CGBuilderBaseTy::CreateIsNull; + llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") { + if (!Addr.hasOffset()) + return CreateIsNull(Addr.getBasePointer(), Name); + // The pointer isn't null if Addr has an offset since offsets can always + // be applied inbound. + return llvm::ConstantInt::getFalse(Context); } using CGBuilderBaseTy::CreateMemCpy; llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemCpyInline; llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { - return CreateMemCpyInline( - Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), getInt64(Size)); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), getInt64(Size)); } using CGBuilderBaseTy::CreateMemMove; llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), - Size, IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemSet; llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemSet(Dest.getPointer(), Value, Size, + return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size, Dest.getAlignment().getAsAlign(), IsVolatile); } using CGBuilderBaseTy::CreateMemSetInline; llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, uint64_t Size) { - return CreateMemSetInline(Dest.getPointer(), + return CreateMemSetInline(emitRawPointerFromAddress(Dest), Dest.getAlignment().getAsAlign(), Value, getInt64(Size)); } @@ -346,16 +417,31 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), - Index, FieldIndex, DbgInfo), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset)); + return Address( + CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr), + Index, FieldIndex, DbgInfo), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + + using CGBuilderBaseTy::CreatePreserveUnionAccessIndex; + Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex, + llvm::MDNode *DbgInfo) { + Addr.replaceBasePointer(CreatePreserveUnionAccessIndex( + Addr.getBasePointer(), FieldIndex, DbgInfo)); + return Addr; } using CGBuilderBaseTy::CreateLaunderInvariantGroup; Address CreateLaunderInvariantGroup(Address Addr) { - return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()), - Addr.isKnownNonNull()); + Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer())); + return Addr; + } + + using CGBuilderBaseTy::CreateStripInvariantGroup; + Address CreateStripInvariantGroup(Address Addr) { + Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer())); + return Addr; } }; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index fdb517eb254d..5ab5917c0c8d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2117,9 +2117,9 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( auto AL = ApplyDebugLocation::CreateArtificial(*this); CharUnits Offset; - Address BufAddr = - Address(Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Int8Ty, - BufferAlignment); + Address BufAddr = makeNaturalAddressForPointer( + Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Ctx.VoidTy, + BufferAlignment); Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()), @@ -2162,7 +2162,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { // Ignore argument 1, the format string. It is not currently used. CallArgList Args; - Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy); + Args.add(RValue::get(BufAddr.emitRawPointer(*this)), Ctx.VoidPtrTy); for (const auto &Item : Layout.Items) { int Size = Item.getSizeByte(); @@ -2202,8 +2202,8 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { if (!isa(ArgVal)) { CleanupKind Cleanup = getARCCleanupKind(); QualType Ty = TheExpr->getType(); - Address Alloca = Address::invalid(); - Address Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); + RawAddress Alloca = RawAddress::invalid(); + RawAddress Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); ArgVal = EmitARCRetain(Ty, ArgVal); Builder.CreateStore(ArgVal, Addr); pushLifetimeExtendedDestroy(Cleanup, Alloca, Ty, @@ -2236,7 +2236,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( Layout, BufAddr.getAlignment()); EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); - return RValue::get(BufAddr.getPointer()); + return RValue::get(BufAddr, *this); } static bool isSpecialUnsignedMultiplySignedResult( @@ -2984,7 +2984,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Check NonnullAttribute/NullabilityArg and Alignment. auto EmitArgCheck = [&](TypeCheckKind Kind, Address A, const Expr *Arg, unsigned ParmNum) { - Value *Val = A.getPointer(); + Value *Val = A.emitRawPointer(*this); EmitNonNullArgCheck(RValue::get(Val), Arg->getType(), Arg->getExprLoc(), FD, ParmNum); @@ -3013,12 +3013,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_va_end: EmitVAStartEnd(BuiltinID == Builtin::BI__va_start ? EmitScalarExpr(E->getArg(0)) - : EmitVAListRef(E->getArg(0)).getPointer(), + : EmitVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID != Builtin::BI__builtin_va_end); return RValue::get(nullptr); case Builtin::BI__builtin_va_copy: { - Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer(); - Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer(); + Value *DstPtr = EmitVAListRef(E->getArg(0)).emitRawPointer(*this); + Value *SrcPtr = EmitVAListRef(E->getArg(1)).emitRawPointer(*this); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy, {DstPtr->getType()}), {DstPtr, SrcPtr}); return RValue::get(nullptr); @@ -3849,13 +3849,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); Address Src = EmitPointerWithAlignment(E->getArg(0)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorLoad( - Src.getElementType(), Src.getPointer(), + Src.getElementType(), Src.emitRawPointer(*this), Align(Src.getAlignment().getQuantity()), Stride, IsVolatile, - ResultTy->getNumRows(), ResultTy->getNumColumns(), - "matrix"); + ResultTy->getNumRows(), ResultTy->getNumColumns(), "matrix"); return RValue::get(Result); } @@ -3870,11 +3870,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, assert(PtrTy && "arg1 must be of pointer type"); bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); - EmitNonNullArgCheck(RValue::get(Dst.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dst.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorStore( - Matrix, Dst.getPointer(), Align(Dst.getAlignment().getQuantity()), - Stride, IsVolatile, MatrixTy->getNumRows(), MatrixTy->getNumColumns()); + Matrix, Dst.emitRawPointer(*this), + Align(Dst.getAlignment().getQuantity()), Stride, IsVolatile, + MatrixTy->getNumRows(), MatrixTy->getNumColumns()); return RValue::get(Result); } @@ -4033,7 +4035,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_bzero: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); Value *SizeVal = EmitScalarExpr(E->getArg(1)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false); return RValue::get(nullptr); @@ -4044,10 +4046,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Builder.CreateMemMove(Dest, Src, SizeVal, false); return RValue::get(nullptr); } @@ -4064,10 +4068,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateMemCpy(Dest, Src, SizeVal, false); if (BuiltinID == Builtin::BImempcpy || BuiltinID == Builtin::BI__builtin_mempcpy) - return RValue::get(Builder.CreateInBoundsGEP(Dest.getElementType(), - Dest.getPointer(), SizeVal)); + return RValue::get(Builder.CreateInBoundsGEP( + Dest.getElementType(), Dest.emitRawPointer(*this), SizeVal)); else - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memcpy_inline: { @@ -4099,7 +4103,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_objc_memmove_collectable: { @@ -4108,7 +4112,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *SizeVal = EmitScalarExpr(E->getArg(2)); CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestAddr, SrcAddr, SizeVal); - return RValue::get(DestAddr.getPointer()); + return RValue::get(DestAddr, *this); } case Builtin::BI__builtin___memmove_chk: { @@ -4125,7 +4129,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemmove: @@ -4136,7 +4140,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitArgCheck(TCK_Store, Dest, E->getArg(0), 0); EmitArgCheck(TCK_Load, Src, E->getArg(1), 1); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemset: case Builtin::BI__builtin_memset: { @@ -4144,10 +4148,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memset_inline: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); @@ -4155,8 +4159,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); uint64_t Size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Builder.CreateMemSetInline(Dest, ByteVal, Size); return RValue::get(nullptr); } @@ -4175,7 +4180,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.getInt8Ty()); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_wmemchr: { // The MSVC runtime library does not provide a definition of wmemchr, so we @@ -4397,14 +4402,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Store the stack pointer to the setjmp buffer. Value *StackAddr = Builder.CreateStackSave(); - assert(Buf.getPointer()->getType() == StackAddr->getType()); + assert(Buf.emitRawPointer(*this)->getType() == StackAddr->getType()); Address StackSaveSlot = Builder.CreateConstInBoundsGEP(Buf, 2); Builder.CreateStore(StackAddr, StackSaveSlot); // Call LLVM's EH setjmp, which is lightweight. Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); - return RValue::get(Builder.CreateCall(F, Buf.getPointer())); + return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); } case Builtin::BI__builtin_longjmp: { Value *Buf = EmitScalarExpr(E->getArg(0)); @@ -5577,7 +5582,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(2)); - llvm::Value *Range = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *Range = NDRangeL.getAddress(*this).emitRawPointer(*this); llvm::Type *RangeTy = NDRangeL.getAddress(*this).getType(); if (NumArgs == 4) { @@ -5686,9 +5691,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, getContext(), Expr::NPC_ValueDependentIsNotNull)) { EventWaitList = llvm::ConstantPointerNull::get(PtrTy); } else { - EventWaitList = E->getArg(4)->getType()->isArrayType() - ? EmitArrayToPointerDecay(E->getArg(4)).getPointer() - : EmitScalarExpr(E->getArg(4)); + EventWaitList = + E->getArg(4)->getType()->isArrayType() + ? EmitArrayToPointerDecay(E->getArg(4)).emitRawPointer(*this) + : EmitScalarExpr(E->getArg(4)); // Convert to generic address space. EventWaitList = Builder.CreatePointerCast(EventWaitList, PtrTy); } @@ -5784,7 +5790,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Type *GenericVoidPtrTy = Builder.getPtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); - llvm::Value *NDRange = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *NDRange = NDRangeL.getAddress(*this).emitRawPointer(*this); auto Info = CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); Value *Kernel = @@ -5869,7 +5875,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy0 = FTy->getParamType(0); if (PTy0 != Arg0Val->getType()) { if (Arg0Ty->isArrayType()) - Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); + Arg0Val = EmitArrayToPointerDecay(Arg0).emitRawPointer(*this); else Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); } @@ -5907,7 +5913,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy1 = FTy->getParamType(1); if (PTy1 != Arg1Val->getType()) { if (Arg1Ty->isArrayType()) - Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer(); + Arg1Val = EmitArrayToPointerDecay(Arg1).emitRawPointer(*this); else Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1); } @@ -5921,7 +5927,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_ms_va_start: case Builtin::BI__builtin_ms_va_end: return RValue::get( - EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(), + EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID == Builtin::BI__builtin_ms_va_start)); case Builtin::BI__builtin_ms_va_copy: { @@ -5963,8 +5969,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // If this is a predefined lib function (e.g. malloc), emit the call // using exactly the normal call path. if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return emitLibraryCall(*this, FD, E, - cast(EmitScalarExpr(E->getCallee()))); + return emitLibraryCall( + *this, FD, E, cast(EmitScalarExpr(E->getCallee()))); // Check that a call to a target specific builtin has the correct target // features. @@ -6081,7 +6087,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(nullptr); return RValue::get(V); case TEK_Aggregate: - return RValue::getAggregate(ReturnValue.getValue(), + return RValue::getAggregate(ReturnValue.getAddress(), ReturnValue.isVolatile()); case TEK_Complex: llvm_unreachable("No current target builtin returns complex"); @@ -8851,7 +8857,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -8878,7 +8884,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp1 = EmitPointerWithAlignment(E->getArg(1)); - Ops.push_back(PtrOp1.getPointer()); + Ops.push_back(PtrOp1.emitRawPointer(*this)); continue; } } @@ -9299,7 +9305,7 @@ Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID, if (ReturnValue.isNull()) return MvecOut; else - return Builder.CreateStore(MvecOut, ReturnValue.getValue()); + return Builder.CreateStore(MvecOut, ReturnValue.getAddress()); } case CustomCodeGen::VST24: { @@ -11479,7 +11485,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -13345,15 +13351,15 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID, if (!getDebugInfo()) { CGM.Error(E->getExprLoc(), "using __builtin_preserve_field_info() without -g"); - return IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + return IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); } // Enable underlying preserve_*_access_index() generation. bool OldIsInPreservedAIRegion = IsInPreservedAIRegion; IsInPreservedAIRegion = true; - Value *FieldAddr = IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + Value *FieldAddr = IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); IsInPreservedAIRegion = OldIsInPreservedAIRegion; ConstantInt *C = cast(EmitScalarExpr(E->getArg(1))); @@ -14345,14 +14351,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { - Address Tmp = CreateMemTemp(E->getArg(0)->getType()); + RawAddress Tmp = CreateMemTemp(E->getArg(0)->getType()); Builder.CreateStore(Ops[0], Tmp); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), Tmp.getPointer()); } case X86::BI_mm_getcsr: case X86::BI__builtin_ia32_stmxcsr: { - Address Tmp = CreateMemTemp(E->getType()); + RawAddress Tmp = CreateMemTemp(E->getType()); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), Tmp.getPointer()); return Builder.CreateLoad(Tmp, "stmxcsr"); @@ -17627,7 +17633,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, SmallVector Ops; for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) if (E->getArg(i)->getType()->isArrayType()) - Ops.push_back(EmitArrayToPointerDecay(E->getArg(i)).getPointer()); + Ops.push_back( + EmitArrayToPointerDecay(E->getArg(i)).emitRawPointer(*this)); else Ops.push_back(EmitScalarExpr(E->getArg(i))); // The first argument of these two builtins is a pointer used to store their @@ -20089,14 +20096,14 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, // Save returned values. assert(II.NumResults); if (II.NumResults == 1) { - Builder.CreateAlignedStore(Result, Dst.getPointer(), + Builder.CreateAlignedStore(Result, Dst.emitRawPointer(*this), CharUnits::fromQuantity(4)); } else { for (unsigned i = 0; i < II.NumResults; ++i) { Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), Dst.getElementType()), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); } @@ -20136,7 +20143,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < II.NumResults; ++i) { Value *V = Builder.CreateAlignedLoad( Src.getElementType(), - Builder.CreateGEP(Src.getElementType(), Src.getPointer(), + Builder.CreateGEP(Src.getElementType(), Src.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, ParamType)); @@ -20208,7 +20215,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsA; ++i) { Value *V = Builder.CreateAlignedLoad( SrcA.getElementType(), - Builder.CreateGEP(SrcA.getElementType(), SrcA.getPointer(), + Builder.CreateGEP(SrcA.getElementType(), SrcA.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, AType)); @@ -20218,7 +20225,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsB; ++i) { Value *V = Builder.CreateAlignedLoad( SrcB.getElementType(), - Builder.CreateGEP(SrcB.getElementType(), SrcB.getPointer(), + Builder.CreateGEP(SrcB.getElementType(), SrcB.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, BType)); @@ -20229,7 +20236,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsC; ++i) { Value *V = Builder.CreateAlignedLoad( SrcC.getElementType(), - Builder.CreateGEP(SrcC.getElementType(), SrcC.getPointer(), + Builder.CreateGEP(SrcC.getElementType(), SrcC.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, CType)); @@ -20239,7 +20246,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsD; ++i) Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); return Result; @@ -20497,7 +20504,7 @@ struct BuiltinAlignArgs { BuiltinAlignArgs(const CallExpr *E, CodeGenFunction &CGF) { QualType AstType = E->getArg(0)->getType(); if (AstType->isArrayType()) - Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(CGF); else Src = CGF.EmitScalarExpr(E->getArg(0)); SrcType = Src->getType(); @@ -21115,7 +21122,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_get: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Function *Callee; if (E->getType().isWebAssemblyExternrefType()) @@ -21129,7 +21136,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_set: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Function *Callee; @@ -21144,13 +21151,13 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_size: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Value = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Value = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_table_size); return Builder.CreateCall(Callee, Value); } case WebAssembly::BI__builtin_wasm_table_grow: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Val = EmitScalarExpr(E->getArg(1)); Value *NElems = EmitScalarExpr(E->getArg(2)); @@ -21167,7 +21174,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_fill: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Value *NElems = EmitScalarExpr(E->getArg(3)); @@ -21185,8 +21192,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_copy: { assert(E->getArg(0)->getType()->isArrayType()); - Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); - Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).getPointer(); + Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).emitRawPointer(*this); Value *DstIdx = EmitScalarExpr(E->getArg(2)); Value *SrcIdx = EmitScalarExpr(E->getArg(3)); Value *NElems = EmitScalarExpr(E->getArg(4)); @@ -21265,7 +21272,7 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, auto MakeCircOp = [this, E](unsigned IntID, bool IsLoad) { // The base pointer is passed by address, so it needs to be loaded. Address A = EmitPointerWithAlignment(E->getArg(0)); - Address BP = Address(A.getPointer(), Int8PtrTy, A.getAlignment()); + Address BP = Address(A.emitRawPointer(*this), Int8PtrTy, A.getAlignment()); llvm::Value *Base = Builder.CreateLoad(BP); // The treatment of both loads and stores is the same: the arguments for // the builtin are the same as the arguments for the intrinsic. @@ -21306,8 +21313,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression // per call. Address DestAddr = EmitPointerWithAlignment(E->getArg(1)); - DestAddr = Address(DestAddr.getPointer(), Int8Ty, DestAddr.getAlignment()); - llvm::Value *DestAddress = DestAddr.getPointer(); + DestAddr = DestAddr.withElementType(Int8Ty); + llvm::Value *DestAddress = DestAddr.emitRawPointer(*this); // Operands are Base, Dest, Modifier. // The intrinsic format in LLVM IR is defined as @@ -21358,8 +21365,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), PredIn}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } // These are identical to the builtins above, except they don't consume @@ -21377,8 +21384,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index b756318c46a9..0cb5b06a519c 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -331,11 +331,11 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, llvm::ConstantInt::get(SizeTy, std::max(1, Args.size()))); // Store pointers to the arguments in a locally allocated launch_args. for (unsigned i = 0; i < Args.size(); ++i) { - llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer(); + llvm::Value *VarPtr = CGF.GetAddrOfLocalVar(Args[i]).emitRawPointer(CGF); llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, PtrTy); CGF.Builder.CreateDefaultAlignedStore( - VoidVarPtr, - CGF.Builder.CreateConstGEP1_32(PtrTy, KernelArgs.getPointer(), i)); + VoidVarPtr, CGF.Builder.CreateConstGEP1_32( + PtrTy, KernelArgs.emitRawPointer(CGF), i)); } llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); @@ -393,9 +393,10 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, /*isVarArg=*/false), addUnderscoredPrefixToName("PopCallConfiguration")); - CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, - {GridDim.getPointer(), BlockDim.getPointer(), - ShmemSize.getPointer(), Stream.getPointer()}); + CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, {GridDim.emitRawPointer(CGF), + BlockDim.emitRawPointer(CGF), + ShmemSize.emitRawPointer(CGF), + Stream.emitRawPointer(CGF)}); // Emit the call to cudaLaunch llvm::Value *Kernel = @@ -405,7 +406,7 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, cudaLaunchKernelFD->getParamDecl(0)->getType()); LaunchKernelArgs.add(RValue::getAggregate(GridDim), Dim3Ty); LaunchKernelArgs.add(RValue::getAggregate(BlockDim), Dim3Ty); - LaunchKernelArgs.add(RValue::get(KernelArgs.getPointer()), + LaunchKernelArgs.add(RValue::get(KernelArgs, CGF), cudaLaunchKernelFD->getParamDecl(3)->getType()); LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(ShmemSize)), cudaLaunchKernelFD->getParamDecl(4)->getType()); @@ -438,8 +439,8 @@ void CGNVCUDARuntime::emitDeviceStubBodyLegacy(CodeGenFunction &CGF, auto TInfo = CGM.getContext().getTypeInfoInChars(A->getType()); Offset = Offset.alignTo(TInfo.Align); llvm::Value *Args[] = { - CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(), - PtrTy), + CGF.Builder.CreatePointerCast( + CGF.GetAddrOfLocalVar(A).emitRawPointer(CGF), PtrTy), llvm::ConstantInt::get(SizeTy, TInfo.Width.getQuantity()), llvm::ConstantInt::get(SizeTy, Offset.getQuantity()), }; diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index a8bf57a277e9..7c6dfc3e59d8 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -20,6 +20,12 @@ using namespace CodeGen; CGCXXABI::~CGCXXABI() { } +Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) { + return CGF.makeNaturalAddressForPointer( + CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(), + CGF.CXXABIThisAlignment); +} + void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { DiagnosticsEngine &Diags = CGF.CGM.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -44,8 +50,12 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *MemPtr, const MemberPointerType *MPT) { ErrorUnsupportedABI(CGF, "calls through member pointers"); - ThisPtrForCall = This.getPointer(); - const auto *FPT = MPT->getPointeeType()->castAs(); + const auto *RD = + cast(MPT->getClass()->castAs()->getDecl()); + ThisPtrForCall = + CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD)); + const FunctionProtoType *FPT = + MPT->getPointeeType()->getAs(); llvm::Constant *FnPtr = llvm::Constant::getNullValue( llvm::PointerType::getUnqual(CGM.getLLVMContext())); return CGCallee::forDirect(FnPtr, FPT); @@ -251,16 +261,15 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, // If we don't need an array cookie, bail out early. if (!requiresArrayCookie(expr, eltTy)) { - allocPtr = ptr.getPointer(); + allocPtr = ptr.emitRawPointer(CGF); numElements = nullptr; cookieSize = CharUnits::Zero(); return; } cookieSize = getArrayCookieSizeImpl(eltTy); - Address allocAddr = - CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); - allocPtr = allocAddr.getPointer(); + Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); + allocPtr = allocAddr.emitRawPointer(CGF); numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); } diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index ad1ad08d0856..c7eccbd0095a 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -57,12 +57,8 @@ protected: llvm::Value *getThisValue(CodeGenFunction &CGF) { return CGF.CXXABIThisValue; } - Address getThisAddress(CodeGenFunction &CGF) { - return Address( - CGF.CXXABIThisValue, - CGF.ConvertTypeForMem(CGF.CXXABIThisDecl->getType()->getPointeeType()), - CGF.CXXABIThisAlignment); - } + + Address getThisAddress(CodeGenFunction &CGF); /// Issue a diagnostic about unsupported features in the ABI. void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S); @@ -475,12 +471,6 @@ public: BaseSubobject Base, const CXXRecordDecl *NearestVBase) = 0; - /// Get the address point of the vtable for the given base subobject while - /// building a constexpr. - virtual llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) = 0; - /// Get the address of the vtable for the given record decl which should be /// used for the vptr at the given offset in RD. virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index b8adf5c26b3a..fb0078214b07 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1037,15 +1037,9 @@ static void forConstantArrayExpansion(CodeGenFunction &CGF, ConstantArrayExpansion *CAE, Address BaseAddr, llvm::function_ref Fn) { - CharUnits EltSize = CGF.getContext().getTypeSizeInChars(CAE->EltTy); - CharUnits EltAlign = - BaseAddr.getAlignment().alignmentOfArrayElement(EltSize); - llvm::Type *EltTy = CGF.ConvertTypeForMem(CAE->EltTy); - for (int i = 0, n = CAE->NumElts; i < n; i++) { - llvm::Value *EltAddr = CGF.Builder.CreateConstGEP2_32( - BaseAddr.getElementType(), BaseAddr.getPointer(), 0, i); - Fn(Address(EltAddr, EltTy, EltAlign)); + Address EltAddr = CGF.Builder.CreateConstGEP2_32(BaseAddr, 0, i); + Fn(EltAddr); } } @@ -1160,9 +1154,10 @@ void CodeGenFunction::ExpandTypeToArgs( } /// Create a temporary allocation for the purposes of coercion. -static Address CreateTempAllocaForCoercion(CodeGenFunction &CGF, llvm::Type *Ty, - CharUnits MinAlign, - const Twine &Name = "tmp") { +static RawAddress CreateTempAllocaForCoercion(CodeGenFunction &CGF, + llvm::Type *Ty, + CharUnits MinAlign, + const Twine &Name = "tmp") { // Don't use an alignment that's worse than what LLVM would prefer. auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlign(Ty); CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign)); @@ -1332,11 +1327,11 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, } // Otherwise do coercion through memory. This is stupid, but simple. - Address Tmp = + RawAddress Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName()); CGF.Builder.CreateMemCpy( - Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), + Src.emitRawPointer(CGF), Src.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinValue())); return CGF.Builder.CreateLoad(Tmp); } @@ -1420,11 +1415,12 @@ static void CreateCoercedStore(llvm::Value *Src, // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); + RawAddress Tmp = + CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); CGF.Builder.CreateStore(Src, Tmp); CGF.Builder.CreateMemCpy( - Dst.getPointer(), Dst.getAlignment().getAsAlign(), Tmp.getPointer(), - Tmp.getAlignment().getAsAlign(), + Dst.emitRawPointer(CGF), Dst.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, DstSize.getFixedValue())); } } @@ -3024,17 +3020,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Indirect: case ABIArgInfo::IndirectAliased: { assert(NumIRArgs == 1); - Address ParamAddr = Address(Fn->getArg(FirstIRArg), ConvertTypeForMem(Ty), - ArgI.getIndirectAlign(), KnownNonNull); + Address ParamAddr = makeNaturalAddressForPointer( + Fn->getArg(FirstIRArg), Ty, ArgI.getIndirectAlign(), false, nullptr, + nullptr, KnownNonNull); if (!hasScalarEvaluationKind(Ty)) { // Aggregates and complex variables are accessed by reference. All we // need to do is realign the value, if requested. Also, if the address // may be aliased, copy it to ensure that the parameter variable is // mutable and has a unique adress, as C requires. - Address V = ParamAddr; if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) { - Address AlignedTemp = CreateMemTemp(Ty, "coerce"); + RawAddress AlignedTemp = CreateMemTemp(Ty, "coerce"); // Copy from the incoming argument pointer to the temporary with the // appropriate alignment. @@ -3044,11 +3040,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, CharUnits Size = getContext().getTypeSizeInChars(Ty); Builder.CreateMemCpy( AlignedTemp.getPointer(), AlignedTemp.getAlignment().getAsAlign(), - ParamAddr.getPointer(), ParamAddr.getAlignment().getAsAlign(), + ParamAddr.emitRawPointer(*this), + ParamAddr.getAlignment().getAsAlign(), llvm::ConstantInt::get(IntPtrTy, Size.getQuantity())); - V = AlignedTemp; + ParamAddr = AlignedTemp; } - ArgVals.push_back(ParamValue::forIndirect(V)); + ArgVals.push_back(ParamValue::forIndirect(ParamAddr)); } else { // Load scalar value from indirect argument. llvm::Value *V = @@ -3162,10 +3159,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, == ParameterABI::SwiftErrorResult) { QualType pointeeTy = Ty->getPointeeType(); assert(pointeeTy->isPointerType()); - Address temp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - Address arg(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + RawAddress temp = + CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); + Address arg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); Builder.CreateStore(incomingErrorValue, temp); V = temp.getPointer(); @@ -3502,7 +3499,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, llvm::LoadInst *load = dyn_cast(retainedValue->stripPointerCasts()); if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer()) + load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) return nullptr; // Okay! Burn it all down. This relies for correctness on the @@ -3539,12 +3536,15 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { + llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); + // Check if a User is a store which pointerOperand is the ReturnValue. // We are looking for stores to the ReturnValue, not for stores of the // ReturnValue to some other location. - auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * { + auto GetStoreIfValid = [&CGF, + ReturnValuePtr](llvm::User *U) -> llvm::StoreInst * { auto *SI = dyn_cast(U); - if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer() || + if (!SI || SI->getPointerOperand() != ReturnValuePtr || SI->getValueOperand()->getType() != CGF.ReturnValue.getElementType()) return nullptr; // These aren't actually possible for non-coerced returns, and we @@ -3558,7 +3558,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { // for something immediately preceding the IP. Sometimes this can // happen with how we generate implicit-returns; it can also happen // with noreturn cleanups. - if (!CGF.ReturnValue.getPointer()->hasOneUse()) { + if (!ReturnValuePtr->hasOneUse()) { llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); if (IP->empty()) return nullptr; @@ -3576,8 +3576,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { return nullptr; } - llvm::StoreInst *store = - GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back()); + llvm::StoreInst *store = GetStoreIfValid(ReturnValuePtr->user_back()); if (!store) return nullptr; // Now do a first-and-dirty dominance check: just walk up the @@ -4121,7 +4120,11 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, } static bool isProvablyNull(llvm::Value *addr) { - return isa(addr); + return llvm::isa_and_nonnull(addr); +} + +static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { + return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. @@ -4129,21 +4132,20 @@ static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; Address srcAddr = srcLV.getAddress(CGF); - assert(!isProvablyNull(srcAddr.getPointer()) && + assert(!isProvablyNull(srcAddr.getBasePointer()) && "shouldn't have writeback for provably null argument"); llvm::BasicBlock *contBB = nullptr; // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); CGF.Builder.CreateCondBr(isNull, contBB, writebackBB); CGF.EmitBlock(writebackBB); } @@ -4247,7 +4249,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getPointer())) { + if (isProvablyNull(srcAddr.getBasePointer())) { args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), CRE->getType()); return; @@ -4276,17 +4278,16 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (provablyNonNull) { - finalArgument = temp.getPointer(); + finalArgument = temp.emitRawPointer(CGF); } else { - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); - finalArgument = CGF.Builder.CreateSelect(isNull, - llvm::ConstantPointerNull::get(destType), - temp.getPointer(), "icr.argument"); + finalArgument = CGF.Builder.CreateSelect( + isNull, llvm::ConstantPointerNull::get(destType), + temp.emitRawPointer(CGF), "icr.argument"); // If we need to copy, then the load has to be conditional, which // means we need control flow. @@ -4410,6 +4411,16 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, std::nullopt); } +void CodeGenFunction::EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, + AbstractCallee AC, unsigned ParmNum) { + if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || + SanOpts.has(SanitizerKind::NullabilityArg))) + return; + + EmitNonNullArgCheck(RValue::get(Addr, *this), ArgType, ArgLoc, AC, ParmNum); +} + // Check if the call is going to use the inalloca convention. This needs to // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged // later, so we can't check it directly. @@ -4750,10 +4761,20 @@ CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) { llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const llvm::Twine &name) { - return EmitNounwindRuntimeCall(callee, std::nullopt, name); + return EmitNounwindRuntimeCall(callee, ArrayRef(), name); } /// Emits a call to the given nounwind runtime function. +llvm::CallInst * +CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef
args, + const llvm::Twine &name) { + SmallVector values; + for (auto arg : args) + values.push_back(arg.emitRawPointer(*this)); + return EmitNounwindRuntimeCall(callee, values, name); +} + llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, @@ -5032,7 +5053,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If we're using inalloca, insert the allocation after the stack save. // FIXME: Do this earlier rather than hacking it in here! - Address ArgMemory = Address::invalid(); + RawAddress ArgMemory = RawAddress::invalid(); if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { const llvm::DataLayout &DL = CGM.getDataLayout(); llvm::Instruction *IP = CallArgs.getStackBase(); @@ -5048,7 +5069,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI->setAlignment(Align.getAsAlign()); AI->setUsedWithInAlloca(true); assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); - ArgMemory = Address(AI, ArgStruct, Align); + ArgMemory = RawAddress(AI, ArgStruct, Align); } ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo); @@ -5057,11 +5078,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); - Address SRetAlloca = Address::invalid(); + RawAddress SRetAlloca = RawAddress::invalid(); llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getValue(); + SRetPtr = ReturnValue.getAddress(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); if (HaveInsertPoint() && ReturnValue.isUnused()) { @@ -5071,15 +5092,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } if (IRFunctionArgs.hasSRetArg()) { - IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); + IRCallArgs[IRFunctionArgs.getSRetArgNo()] = + getAsNaturalPointerTo(SRetPtr, RetTy); } else if (RetAI.isInAlloca()) { Address Addr = Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex()); - Builder.CreateStore(SRetPtr.getPointer(), Addr); + Builder.CreateStore(getAsNaturalPointerTo(SRetPtr, RetTy), Addr); } } - Address swiftErrorTemp = Address::invalid(); + RawAddress swiftErrorTemp = RawAddress::invalid(); Address swiftErrorArg = Address::invalid(); // When passing arguments using temporary allocas, we need to add the @@ -5112,9 +5134,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 0); assert(getTarget().getTriple().getArch() == llvm::Triple::x86); if (I->isAggregate()) { - Address Addr = I->hasLValue() - ? I->getKnownLValue().getAddress(*this) - : I->getKnownRValue().getAggregateAddress(); + RawAddress Addr = I->hasLValue() + ? I->getKnownLValue().getAddress(*this) + : I->getKnownRValue().getAggregateAddress(); llvm::Instruction *Placeholder = cast(Addr.getPointer()); @@ -5138,7 +5160,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else if (ArgInfo.getInAllocaIndirect()) { // Make a temporary alloca and store the address of it into the argument // struct. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, getContext().getTypeAlignInChars(I->Ty), "indirect-arg-temp"); I->copyInto(*this, Addr); @@ -5160,12 +5182,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 1); if (!I->isAggregate()) { // Make a temporary alloca to pass the argument. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "indirect-arg-temp"); - llvm::Value *Val = Addr.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(Addr, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(Addr.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; I->copyInto(*this, Addr); @@ -5181,7 +5203,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Address Addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); - llvm::Value *V = Addr.getPointer(); CharUnits Align = ArgInfo.getIndirectAlign(); const llvm::DataLayout *TD = &CGM.getDataLayout(); @@ -5192,8 +5213,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, bool NeedCopy = false; if (Addr.getAlignment() < Align && - llvm::getOrEnforceKnownAlignment(V, Align.getAsAlign(), *TD) < - Align.getAsAlign()) { + llvm::getOrEnforceKnownAlignment(Addr.emitRawPointer(*this), + Align.getAsAlign(), + *TD) < Align.getAsAlign()) { NeedCopy = true; } else if (I->hasLValue()) { auto LV = I->getKnownLValue(); @@ -5224,11 +5246,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (NeedCopy) { // Create an aligned temporary, and copy to it. - Address AI = CreateMemTempWithoutCast( + RawAddress AI = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); - llvm::Value *Val = AI.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(AI, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(AI.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; // Emit lifetime markers for the temporary alloca. @@ -5245,6 +5267,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, I->copyInto(*this, AI); } else { // Skip the extra memcpy call. + llvm::Value *V = getAsNaturalPointerTo(Addr, I->Ty); auto *T = llvm::PointerType::get( CGM.getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace()); @@ -5284,8 +5307,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); QualType pointeeTy = I->Ty->getPointeeType(); - swiftErrorArg = Address(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + swiftErrorArg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); swiftErrorTemp = CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); @@ -5422,7 +5445,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *tempSize = nullptr; Address addr = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); if (I->isAggregate()) { addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); @@ -5856,7 +5879,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return RValue::getComplex(std::make_pair(Real, Imag)); } case TEK_Aggregate: { - Address DestPtr = ReturnValue.getValue(); + Address DestPtr = ReturnValue.getAddress(); bool DestIsVolatile = ReturnValue.isVolatile(); if (!DestPtr.isValid()) { diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 1bd48a072593..6b676ac196db 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -377,6 +377,7 @@ public: Address getValue() const { return Addr; } bool isUnused() const { return IsUnused; } bool isExternallyDestructed() const { return IsExternallyDestructed; } + Address getAddress() const { return Addr; } }; /// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 34319381901a..8c1c8ee455d2 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -139,8 +139,9 @@ Address CodeGenFunction::LoadCXXThisAddress() { CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent()); } - llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType()); - return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull); + return makeNaturalAddressForPointer( + LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment, + false, nullptr, nullptr, KnownNonNull); } /// Emit the address of a field using a member data pointer. @@ -270,7 +271,7 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, } // Apply the base offset. - llvm::Value *ptr = addr.getPointer(); + llvm::Value *ptr = addr.emitRawPointer(CGF); ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr"); // If we have a virtual component, the alignment of the result will @@ -338,8 +339,8 @@ Address CodeGenFunction::GetAddressOfBaseClass( if (sanitizePerformTypeCheck()) { SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, !NullCheckValue); - EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(), - DerivedTy, DerivedAlign, SkippedChecks); + EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy, + DerivedAlign, SkippedChecks); } return Value.withElementType(BaseValueTy); } @@ -354,7 +355,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull"); endBB = createBasicBlock("cast.end"); - llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer()); + llvm::Value *isNull = Builder.CreateIsNull(Value); Builder.CreateCondBr(isNull, endBB, notNullBB); EmitBlock(notNullBB); } @@ -363,14 +364,15 @@ Address CodeGenFunction::GetAddressOfBaseClass( SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, - Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks); + Value.emitRawPointer(*this), DerivedTy, DerivedAlign, + SkippedChecks); } // Compute the virtual offset. llvm::Value *VirtualOffset = nullptr; if (VBase) { VirtualOffset = - CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); + CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); } // Apply both offsets. @@ -387,7 +389,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( EmitBlock(endBB); llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result"); - PHI->addIncoming(Value.getPointer(), notNullBB); + PHI->addIncoming(Value.emitRawPointer(*this), notNullBB); PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB); Value = Value.withPointer(PHI, NotKnownNonNull); } @@ -424,15 +426,19 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, CastNotNull = createBasicBlock("cast.notnull"); CastEnd = createBasicBlock("cast.end"); - llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } // Apply the offset. - llvm::Value *Value = BaseAddr.getPointer(); - Value = Builder.CreateInBoundsGEP( - Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr"); + Address Addr = BaseAddr.withElementType(Int8Ty); + Addr = Builder.CreateInBoundsGEP( + Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty, + CGM.getClassPointerAlignment(Derived), "sub.ptr"); + + // Just cast. + Addr = Addr.withElementType(DerivedValueTy); // Produce a PHI if we had a null-check. if (NullCheckValue) { @@ -441,13 +447,15 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, Builder.CreateBr(CastEnd); EmitBlock(CastEnd); + llvm::Value *Value = Addr.emitRawPointer(*this); llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); PHI->addIncoming(Value, CastNotNull); PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); - Value = PHI; + return Address(PHI, Addr.getElementType(), + CGM.getClassPointerAlignment(Derived)); } - return Address(Value, DerivedValueTy, CGM.getClassPointerAlignment(Derived)); + return Addr; } llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, @@ -1719,7 +1727,7 @@ namespace { // Use the base class declaration location as inline DebugLocation. All // fields of the class are destroyed. DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass); - EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(), + EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF), BaseSize.getQuantity()); // Prevent the current stack frame from disappearing from the stack trace. @@ -2022,7 +2030,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, // Find the end of the array. llvm::Type *elementType = arrayBase.getElementType(); - llvm::Value *arrayBegin = arrayBase.getPointer(); + llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this); llvm::Value *arrayEnd = Builder.CreateInBoundsGEP( elementType, arrayBegin, numElements, "arrayctor.end"); @@ -2118,14 +2126,15 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, Address This = ThisAVS.getAddress(); LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace(); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = + getAsNaturalPointerTo(This, D->getThisType()->getPointeeType()); if (SlotAS != ThisAS) { unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); llvm::Type *NewType = llvm::PointerType::get(getLLVMContext(), TargetThisAS); - ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), - ThisAS, SlotAS, NewType); + ThisPtr = getTargetHooks().performAddrSpaceCast(*this, ThisPtr, ThisAS, + SlotAS, NewType); } // Push the this ptr. @@ -2194,7 +2203,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const CXXRecordDecl *ClassDecl = D->getParent(); if (!NewPointerIsChecked) - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This, getContext().getRecordType(ClassDecl), CharUnits::Zero()); if (D->isTrivial() && D->isDefaultConstructor()) { @@ -2207,10 +2216,9 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // model that copy. if (isMemcpyEquivalentSpecialMember(D)) { assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); - QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); - Address Src = Address(Args[1].getRValue(*this).getScalarVal(), ConvertTypeForMem(SrcTy), - CGM.getNaturalTypeAlignment(SrcTy)); + Address Src = makeNaturalAddressForPointer( + Args[1].getRValue(*this).getScalarVal(), SrcTy); LValue SrcLVal = MakeAddrLValue(Src, SrcTy); QualType DestTy = getContext().getTypeDeclType(ClassDecl); LValue DestLVal = MakeAddrLValue(This, DestTy); @@ -2263,7 +2271,9 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall( const CXXConstructorDecl *D, bool ForVirtualBase, Address This, bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) { CallArgList Args; - CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType()); + CallArg ThisArg(RValue::get(getAsNaturalPointerTo( + This, D->getThisType()->getPointeeType())), + D->getThisType()); // Forward the parameters. if (InheritedFromVBase && @@ -2388,12 +2398,14 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, CallArgList Args; // Push the this ptr. - Args.add(RValue::get(This.getPointer()), D->getThisType()); + Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())), + D->getThisType()); // Push the src ptr. QualType QT = *(FPT->param_type_begin()); llvm::Type *t = CGM.getTypes().ConvertType(QT); - llvm::Value *SrcVal = Builder.CreateBitCast(Src.getPointer(), t); + llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType()); + llvm::Value *SrcVal = Builder.CreateBitCast(Val, t); Args.add(RValue::get(SrcVal), QT); // Skip over first argument (Src). @@ -2418,7 +2430,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // this Address This = LoadCXXThisAddress(); - DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); + DelegateArgs.add(RValue::get(getAsNaturalPointerTo( + This, (*I)->getType()->getPointeeType())), + (*I)->getType()); ++I; // FIXME: The location of the VTT parameter in the parameter list is @@ -2775,7 +2789,7 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived, if (MayBeNull) { llvm::Value *DerivedNotNull = - Builder.CreateIsNotNull(Derived.getPointer(), "cast.nonnull"); + Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull"); llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check"); ContBlock = createBasicBlock("cast.cont"); @@ -2976,7 +2990,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); Address ThisPtr = GetAddrOfBlockDecl(variable); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType); // Add the rest of the parameters. for (auto *param : BD->parameters()) @@ -3004,7 +3018,7 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { QualType LambdaType = getContext().getRecordType(Lambda); QualType ThisType = getContext().getPointerType(LambdaType); Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType); EmitLambdaDelegatingInvokeBody(MD, CallArgs); } diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index f87caf050eea..e6f8e6873004 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -27,7 +27,7 @@ bool DominatingValue::saved_type::needsSaving(RValue rv) { if (rv.isScalar()) return DominatingLLVMValue::needsSaving(rv.getScalarVal()); if (rv.isAggregate()) - return DominatingLLVMValue::needsSaving(rv.getAggregatePointer()); + return DominatingValue
::needsSaving(rv.getAggregateAddress()); return true; } @@ -35,69 +35,40 @@ DominatingValue::saved_type DominatingValue::saved_type::save(CodeGenFunction &CGF, RValue rv) { if (rv.isScalar()) { llvm::Value *V = rv.getScalarVal(); - - // These automatically dominate and don't need to be saved. - if (!DominatingLLVMValue::needsSaving(V)) - return saved_type(V, nullptr, ScalarLiteral); - - // Everything else needs an alloca. - Address addr = - CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue"); - CGF.Builder.CreateStore(V, addr); - return saved_type(addr.getPointer(), nullptr, ScalarAddress); + return saved_type(DominatingLLVMValue::save(CGF, V), + DominatingLLVMValue::needsSaving(V) ? ScalarAddress + : ScalarLiteral); } if (rv.isComplex()) { CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); - llvm::Type *ComplexTy = - llvm::StructType::get(V.first->getType(), V.second->getType()); - Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex"); - CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0)); - CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1)); - return saved_type(addr.getPointer(), nullptr, ComplexAddress); + return saved_type(DominatingLLVMValue::save(CGF, V.first), + DominatingLLVMValue::save(CGF, V.second)); } assert(rv.isAggregate()); - Address V = rv.getAggregateAddress(); // TODO: volatile? - if (!DominatingLLVMValue::needsSaving(V.getPointer())) - return saved_type(V.getPointer(), V.getElementType(), AggregateLiteral, - V.getAlignment().getQuantity()); - - Address addr = - CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue"); - CGF.Builder.CreateStore(V.getPointer(), addr); - return saved_type(addr.getPointer(), V.getElementType(), AggregateAddress, - V.getAlignment().getQuantity()); + Address V = rv.getAggregateAddress(); + return saved_type( + DominatingValue
::save(CGF, V), rv.isVolatileQualified(), + DominatingValue
::needsSaving(V) ? AggregateAddress + : AggregateLiteral); } /// Given a saved r-value produced by SaveRValue, perform the code /// necessary to restore it to usability at the current insertion /// point. RValue DominatingValue::saved_type::restore(CodeGenFunction &CGF) { - auto getSavingAddress = [&](llvm::Value *value) { - auto *AI = cast(value); - return Address(value, AI->getAllocatedType(), - CharUnits::fromQuantity(AI->getAlign().value())); - }; switch (K) { case ScalarLiteral: - return RValue::get(Value); case ScalarAddress: - return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value))); + return RValue::get(DominatingLLVMValue::restore(CGF, Vals.first)); case AggregateLiteral: + case AggregateAddress: return RValue::getAggregate( - Address(Value, ElementType, CharUnits::fromQuantity(Align))); - case AggregateAddress: { - auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value)); - return RValue::getAggregate( - Address(addr, ElementType, CharUnits::fromQuantity(Align))); - } + DominatingValue
::restore(CGF, AggregateAddr), IsVolatile); case ComplexAddress: { - Address address = getSavingAddress(Value); - llvm::Value *real = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 0)); - llvm::Value *imag = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 1)); + llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first); + llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second); return RValue::getComplex(real, imag); } } @@ -294,14 +265,14 @@ void EHScopeStack::popNullFixups() { BranchFixups.pop_back(); } -Address CodeGenFunction::createCleanupActiveFlag() { +RawAddress CodeGenFunction::createCleanupActiveFlag() { // Create a variable to decide whether the cleanup needs to be run. - Address active = CreateTempAllocaWithoutCast( + RawAddress active = CreateTempAllocaWithoutCast( Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); // Initialize it to false at a site that's guaranteed to be run // before each evaluation. - setBeforeOutermostConditional(Builder.getFalse(), active); + setBeforeOutermostConditional(Builder.getFalse(), active, *this); // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); @@ -309,7 +280,7 @@ Address CodeGenFunction::createCleanupActiveFlag() { return active; } -void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { +void CodeGenFunction::initFullExprCleanupWithFlag(RawAddress ActiveFlag) { // Set that as the active flag in the cleanup. EHCleanupScope &cleanup = cast(*EHStack.begin()); assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); @@ -322,15 +293,17 @@ void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { void EHScopeStack::Cleanup::anchor() {} static void createStoreInstBefore(llvm::Value *value, Address addr, - llvm::Instruction *beforeInst) { - auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + auto store = new llvm::StoreInst(value, addr.emitRawPointer(CGF), beforeInst); store->setAlignment(addr.getAlignment().getAsAlign()); } static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, - llvm::Instruction *beforeInst) { - return new llvm::LoadInst(addr.getElementType(), addr.getPointer(), name, - false, addr.getAlignment().getAsAlign(), + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + return new llvm::LoadInst(addr.getElementType(), addr.emitRawPointer(CGF), + name, false, addr.getAlignment().getAsAlign(), beforeInst); } @@ -357,8 +330,8 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF, // entry which we're currently popping. if (Fixup.OptimisticBranchBlock == nullptr) { createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex), - CGF.getNormalCleanupDestSlot(), - Fixup.InitialBranch); + CGF.getNormalCleanupDestSlot(), Fixup.InitialBranch, + CGF); Fixup.InitialBranch->setSuccessor(0, CleanupEntry); } @@ -385,7 +358,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, if (llvm::BranchInst *Br = dyn_cast(Term)) { assert(Br->isUnconditional()); auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(), - "cleanup.dest", Term); + "cleanup.dest", Term, CGF); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); Br->eraseFromParent(); @@ -513,8 +486,8 @@ void CodeGenFunction::PopCleanupBlocks( I += Header.getSize(); if (Header.isConditional()) { - Address ActiveFlag = - reinterpret_cast
(LifetimeExtendedCleanupStack[I]); + RawAddress ActiveFlag = + reinterpret_cast(LifetimeExtendedCleanupStack[I]); initFullExprCleanupWithFlag(ActiveFlag); I += sizeof(ActiveFlag); } @@ -888,7 +861,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (NormalCleanupDestSlot->hasOneUse()) { NormalCleanupDestSlot->user_back()->eraseFromParent(); NormalCleanupDestSlot->eraseFromParent(); - NormalCleanupDest = Address::invalid(); + NormalCleanupDest = RawAddress::invalid(); } llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); @@ -912,9 +885,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // pass the abnormal exit flag to Fn (SEH cleanup) cleanupFlags.setHasExitSwitch(); - llvm::LoadInst *Load = - createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest", - nullptr); + llvm::LoadInst *Load = createLoadInstBefore( + getNormalCleanupDestSlot(), "cleanup.dest", nullptr, *this); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Default, SwitchCapacity); @@ -961,8 +933,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (!Fixup.Destination) continue; if (!Fixup.OptimisticBranchBlock) { createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex), - getNormalCleanupDestSlot(), - Fixup.InitialBranch); + getNormalCleanupDestSlot(), Fixup.InitialBranch, + *this); Fixup.InitialBranch->setSuccessor(0, NormalEntry); } Fixup.OptimisticBranchBlock = NormalExit; @@ -1135,7 +1107,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { // Store the index at the start. llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); - createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI); + createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI, *this); // Adjust BI to point to the first cleanup block. { @@ -1269,9 +1241,9 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF, // If we're in a conditional block, ignore the dominating IP and // use the outermost conditional branch. if (CGF.isInConditionalBranch()) { - CGF.setBeforeOutermostConditional(value, var); + CGF.setBeforeOutermostConditional(value, var, CGF); } else { - createStoreInstBefore(value, var, dominatingIP); + createStoreInstBefore(value, var, dominatingIP, CGF); } } @@ -1321,7 +1293,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, Scope.setActive(false); } -Address CodeGenFunction::getNormalCleanupDestSlot() { +RawAddress CodeGenFunction::getNormalCleanupDestSlot() { if (!NormalCleanupDest.isValid()) NormalCleanupDest = CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h index 7a7344c07160..03e4a29d7b3d 100644 --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -333,7 +333,7 @@ public: Address getActiveFlag() const { return ActiveFlag; } - void setActiveFlag(Address Var) { + void setActiveFlag(RawAddress Var) { assert(Var.getAlignment().isOne()); ActiveFlag = Var; } diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index b7142ec08af9..93ca711f716f 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -867,8 +867,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { EmitStmt(S.getPromiseDeclStmt()); Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl()); - auto *PromiseAddrVoidPtr = - new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId); + auto *PromiseAddrVoidPtr = new llvm::BitCastInst( + PromiseAddr.emitRawPointer(*this), VoidPtrTy, "", CoroId); // Update CoroId to refer to the promise. We could not do it earlier because // promise local variable was not emitted yet. CoroId->setArgOperand(1, PromiseAddrVoidPtr); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 2ef5ed04af30..267f2e40a7bb 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1461,7 +1461,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { bool EmitDebugInfo = DI && CGM.getCodeGenOpts().hasReducedDebugInfo(); Address address = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); Address OpenMPLocalAddr = Address::invalid(); if (CGM.getLangOpts().OpenMPIRBuilder) OpenMPLocalAddr = OMPBuilderCBHelpers::getAddressOfLocalVariable(*this, &D); @@ -1524,7 +1524,10 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // return slot, so that we can elide the copy when returning this // variable (C++0x [class.copy]p34). address = ReturnValue; - AllocaAddr = ReturnValue; + AllocaAddr = + RawAddress(ReturnValue.emitRawPointer(*this), + ReturnValue.getElementType(), ReturnValue.getAlignment()); + ; if (const RecordType *RecordTy = Ty->getAs()) { const auto *RD = RecordTy->getDecl(); @@ -1535,7 +1538,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // to this variable. Set it to zero to indicate that NRVO was not // applied. llvm::Value *Zero = Builder.getFalse(); - Address NRVOFlag = + RawAddress NRVOFlag = CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo"); EnsureInsertPoint(); Builder.CreateStore(Zero, NRVOFlag); @@ -1678,7 +1681,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { } if (D.hasAttr() && HaveInsertPoint()) - EmitVarAnnotations(&D, address.getPointer()); + EmitVarAnnotations(&D, address.emitRawPointer(*this)); // Make sure we call @llvm.lifetime.end. if (emission.useLifetimeMarkers()) @@ -1851,12 +1854,13 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, llvm::Value *BaseSizeInChars = llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); Address Begin = Loc.withElementType(Int8Ty); - llvm::Value *End = Builder.CreateInBoundsGEP( - Begin.getElementType(), Begin.getPointer(), SizeVal, "vla.end"); + llvm::Value *End = Builder.CreateInBoundsGEP(Begin.getElementType(), + Begin.emitRawPointer(*this), + SizeVal, "vla.end"); llvm::BasicBlock *OriginBB = Builder.GetInsertBlock(); EmitBlock(LoopBB); llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur"); - Cur->addIncoming(Begin.getPointer(), OriginBB); + Cur->addIncoming(Begin.emitRawPointer(*this), OriginBB); CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); auto *I = Builder.CreateMemCpy(Address(Cur, Int8Ty, CurAlign), @@ -2283,7 +2287,7 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, checkZeroLength = false; } - llvm::Value *begin = addr.getPointer(); + llvm::Value *begin = addr.emitRawPointer(*this); llvm::Value *end = Builder.CreateInBoundsGEP(addr.getElementType(), begin, length); emitArrayDestroy(begin, end, type, elementAlign, destroyer, @@ -2543,7 +2547,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } Address DeclPtr = Address::invalid(); - Address AllocaPtr = Address::invalid(); + RawAddress AllocaPtr = Address::invalid(); bool DoStore = false; bool IsScalar = hasScalarEvaluationKind(Ty); bool UseIndirectDebugAddress = false; @@ -2555,8 +2559,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // Indirect argument is in alloca address space, which may be different // from the default address space. auto AllocaAS = CGM.getASTAllocaAddressSpace(); - auto *V = DeclPtr.getPointer(); - AllocaPtr = DeclPtr; + auto *V = DeclPtr.emitRawPointer(*this); + AllocaPtr = RawAddress(V, DeclPtr.getElementType(), DeclPtr.getAlignment()); // For truly ABI indirect arguments -- those that are not `byval` -- store // the address of the argument on the stack to preserve debug information. @@ -2695,7 +2699,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } if (D.hasAttr()) - EmitVarAnnotations(&D, DeclPtr.getPointer()); + EmitVarAnnotations(&D, DeclPtr.emitRawPointer(*this)); // We can only check return value nullability if all arguments to the // function satisfy their nullability preconditions. This makes it necessary diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 5a9d06da12de..34f289334a7d 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -397,7 +397,7 @@ namespace { void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { // Make sure the exception object is cleaned up if there's an // exception during initialization. - pushFullExprCleanup(EHCleanup, addr.getPointer()); + pushFullExprCleanup(EHCleanup, addr.emitRawPointer(*this)); EHScopeStack::stable_iterator cleanup = EHStack.stable_begin(); // __cxa_allocate_exception returns a void*; we need to cast this @@ -416,8 +416,8 @@ void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { /*IsInit*/ true); // Deactivate the cleanup block. - DeactivateCleanupBlock(cleanup, - cast(typedAddr.getPointer())); + DeactivateCleanupBlock( + cleanup, cast(typedAddr.emitRawPointer(*this))); } Address CodeGenFunction::getExceptionSlot() { @@ -1834,7 +1834,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, llvm::Value *ParentFP) { llvm::CallInst *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast(ParentVar.getPointer())) { + if (auto *ParentAlloca = + dyn_cast_or_null(ParentVar.getBasePointer())) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( @@ -1851,8 +1852,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, // If the parent didn't have an alloca, we're doing some nested outlining. // Just clone the existing localrecover call, but tweak the FP argument to // use our FP value. All other arguments are constants. - auto *ParentRecover = - cast(ParentVar.getPointer()->stripPointerCasts()); + auto *ParentRecover = cast( + ParentVar.emitRawPointer(*this)->stripPointerCasts()); assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && "expected alloca or localrecover in parent LocalDeclMap"); RecoverCall = cast(ParentRecover->clone()); @@ -1925,7 +1926,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, if (isa(D) && D->getType() == getContext().VoidPtrTy) { assert(D->getName().starts_with("frame_pointer")); - FramePtrAddrAlloca = cast(I.second.getPointer()); + FramePtrAddrAlloca = + cast(I.second.getBasePointer()); break; } } @@ -1986,7 +1988,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + CXXThisValue = + ThisFieldLValue.getAddress(*this).emitRawPointer(*this); } else { CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) .getScalarVal(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6491835cf8ef..36872c0fedb7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -65,21 +65,21 @@ static llvm::cl::opt ClSanitizeDebugDeoptimization( /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. -Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, - CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize) { +RawAddress +CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize) { auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); Alloca->setAlignment(Align.getAsAlign()); - return Address(Alloca, Ty, Align, KnownNonNull); + return RawAddress(Alloca, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. The alloca is casted to default address space if necessary. -Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize, - Address *AllocaAddr) { +RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize, + RawAddress *AllocaAddr) { auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); if (AllocaAddr) *AllocaAddr = Alloca; @@ -101,7 +101,7 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, Ty->getPointerTo(DestAddrSpace), /*non-null*/ true); } - return Address(V, Ty, Align, KnownNonNull); + return RawAddress(V, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates an alloca and inserts it into the entry @@ -120,28 +120,29 @@ llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, /// default alignment of the corresponding LLVM type, which is *not* /// guaranteed to be related in any way to the expected alignment of /// an AST type that might have been lowered to Ty. -Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name) { CharUnits Align = CharUnits::fromQuantity(CGM.getDataLayout().getPrefTypeAlign(Ty)); return CreateTempAlloca(Ty, Align, Name); } -Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { +RawAddress CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { CharUnits Align = getContext().getTypeAlignInChars(Ty); return CreateTempAlloca(ConvertType(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, - Address *Alloca) { +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, + RawAddress *Alloca) { // FIXME: Should we prefer the preferred type alignment here? return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, - const Twine &Name, Address *Alloca) { - Address Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, - /*ArraySize=*/nullptr, Alloca); +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, + const Twine &Name, + RawAddress *Alloca) { + RawAddress Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, + /*ArraySize=*/nullptr, Alloca); if (Ty->isConstantMatrixType()) { auto *ArrayTy = cast(Result.getElementType()); @@ -154,13 +155,14 @@ Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, return Result; } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + CharUnits Align, + const Twine &Name) { return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + const Twine &Name) { return CreateMemTempWithoutCast(Ty, getContext().getTypeAlignInChars(Ty), Name); } @@ -359,7 +361,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } else { CleanupFn = CGF.CGM.getAddrAndTypeOfCXXStructor( GlobalDecl(ReferenceTemporaryDtor, Dtor_Complete)); - CleanupArg = cast(ReferenceTemporary.getPointer()); + CleanupArg = cast(ReferenceTemporary.emitRawPointer(CGF)); } CGF.CGM.getCXXABI().registerGlobalDtor( CGF, *cast(M->getExtendingDecl()), CleanupFn, CleanupArg); @@ -384,10 +386,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } } -static Address createReferenceTemporary(CodeGenFunction &CGF, - const MaterializeTemporaryExpr *M, - const Expr *Inner, - Address *Alloca = nullptr) { +static RawAddress createReferenceTemporary(CodeGenFunction &CGF, + const MaterializeTemporaryExpr *M, + const Expr *Inner, + RawAddress *Alloca = nullptr) { auto &TCG = CGF.getTargetHooks(); switch (M->getStorageDuration()) { case SD_FullExpression: @@ -416,7 +418,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, GV->getValueType()->getPointerTo( CGF.getContext().getTargetAddressSpace(LangAS::Default))); // FIXME: Should we put the new global into a COMDAT? - return Address(C, GV->getValueType(), alignment); + return RawAddress(C, GV->getValueType(), alignment); } return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca); } @@ -448,7 +450,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { auto ownership = M->getType().getObjCLifetime(); if (ownership != Qualifiers::OCL_None && ownership != Qualifiers::OCL_ExplicitNone) { - Address Object = createReferenceTemporary(*this, M, E); + RawAddress Object = createReferenceTemporary(*this, M, E); if (auto *Var = dyn_cast(Object.getPointer())) { llvm::Type *Ty = ConvertTypeForMem(E->getType()); Object = Object.withElementType(Ty); @@ -502,8 +504,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { } // Create and initialize the reference temporary. - Address Alloca = Address::invalid(); - Address Object = createReferenceTemporary(*this, M, E, &Alloca); + RawAddress Alloca = Address::invalid(); + RawAddress Object = createReferenceTemporary(*this, M, E, &Alloca); if (auto *Var = dyn_cast( Object.getPointer()->stripPointerCasts())) { llvm::Type *TemporaryType = ConvertTypeForMem(E->getType()); @@ -1111,12 +1113,12 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( } else if (const MemberExpr *ME = dyn_cast(StructBase)) { LValue LV = EmitMemberExpr(ME); Address Addr = LV.getAddress(*this); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else if (StructBase->getType()->isPointerType()) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else { return nullptr; } @@ -1282,8 +1284,7 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { if (BaseInfo) BaseInfo->mergeForCast(TargetTypeBaseInfo); - Addr = Address(Addr.getPointer(), Addr.getElementType(), Align, - IsKnownNonNull); + Addr.setAlignment(Align); } } @@ -1300,8 +1301,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, CGF.ConvertTypeForMem(E->getType()->getPointeeType()); Addr = Addr.withElementType(ElemTy); if (CE->getCastKind() == CK_AddressSpaceConversion) - Addr = CGF.Builder.CreateAddrSpaceCast(Addr, - CGF.ConvertType(E->getType())); + Addr = CGF.Builder.CreateAddrSpaceCast( + Addr, CGF.ConvertType(E->getType()), ElemTy); return Addr; } break; @@ -1364,10 +1365,9 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. - CharUnits Align = - CGF.CGM.getNaturalPointeeTypeAlignment(E->getType(), BaseInfo, TBAAInfo); - llvm::Type *ElemTy = CGF.ConvertTypeForMem(E->getType()->getPointeeType()); - return Address(CGF.EmitScalarExpr(E), ElemTy, Align, IsKnownNonNull); + return CGF.makeNaturalAddressForPointer( + CGF.EmitScalarExpr(E), E->getType()->getPointeeType(), CharUnits(), + /*ForPointeeType=*/true, BaseInfo, TBAAInfo, IsKnownNonNull); } /// EmitPointerWithAlignment - Given an expression of pointer type, try to @@ -1468,8 +1468,7 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) { if (IsBaseCXXThis || isa(ME->getBase())) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(*this), E->getType(), - LV.getAlignment(), SkippedChecks); + EmitTypeCheck(TCK, E->getExprLoc(), LV, E->getType(), SkippedChecks); } return LV; } @@ -1581,11 +1580,11 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, // Defend against branches out of gnu statement expressions surrounded by // cleanups. Address Addr = LV.getAddress(*this); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.getBasePointer(); Scope.ForceCleanup({&V}); - return LValue::MakeAddr(Addr.withPointer(V, Addr.isKnownNonNull()), - LV.getType(), getContext(), LV.getBaseInfo(), - LV.getTBAAInfo()); + Addr.replaceBasePointer(V); + return LValue::MakeAddr(Addr, LV.getType(), getContext(), + LV.getBaseInfo(), LV.getTBAAInfo()); } // FIXME: Is it possible to create an ExprWithCleanups that produces a // bitfield lvalue or some other non-simple lvalue? @@ -1929,7 +1928,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getPointer())) + if (auto *GV = dyn_cast(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2039,8 +2038,9 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) { // Convert the pointer of \p Addr to a pointer to a vector (the value type of // MatrixType), if it points to a array (the memory type of MatrixType). -static Address MaybeConvertMatrixAddress(Address Addr, CodeGenFunction &CGF, - bool IsVector = true) { +static RawAddress MaybeConvertMatrixAddress(RawAddress Addr, + CodeGenFunction &CGF, + bool IsVector = true) { auto *ArrayTy = dyn_cast(Addr.getElementType()); if (ArrayTy && IsVector) { auto *VectorTy = llvm::FixedVectorType::get(ArrayTy->getElementType(), @@ -2077,7 +2077,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isInit, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getPointer())) + if (auto *GV = dyn_cast(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2432,14 +2432,12 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); llvm::Type *ResultType = IntPtrTy; Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); - llvm::Value *RHS = dst.getPointer(); + llvm::Value *RHS = dst.emitRawPointer(*this); RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - llvm::Value *LHS = - Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, - "sub.ptr.lhs.cast"); + llvm::Value *LHS = Builder.CreatePtrToInt(LvalueDst.emitRawPointer(*this), + ResultType, "sub.ptr.lhs.cast"); llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, - BytesBetween); + CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, BytesBetween); } else if (Dst.isGlobalObjCRef()) { CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, Dst.isThreadLocalRef()); @@ -2770,12 +2768,9 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(*this), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - - QualType PointeeType = RefLVal.getType()->getPointeeType(); - CharUnits Align = CGM.getNaturalTypeAlignment( - PointeeType, PointeeBaseInfo, PointeeTBAAInfo, - /* forPointeeType= */ true); - return Address(Load, ConvertTypeForMem(PointeeType), Align); + return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + PointeeBaseInfo, PointeeTBAAInfo); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { @@ -2792,10 +2787,9 @@ Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, LValueBaseInfo *BaseInfo, TBAAAccessInfo *TBAAInfo) { llvm::Value *Addr = Builder.CreateLoad(Ptr); - return Address(Addr, ConvertTypeForMem(PtrTy->getPointeeType()), - CGM.getNaturalTypeAlignment(PtrTy->getPointeeType(), BaseInfo, - TBAAInfo, - /*forPointeeType=*/true)); + return makeNaturalAddressForPointer(Addr, PtrTy->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + BaseInfo, TBAAInfo); } LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, @@ -2991,7 +2985,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { /* BaseInfo= */ nullptr, /* TBAAInfo= */ nullptr, /* forPointeeType= */ true); - Addr = Address(Val, ConvertTypeForMem(E->getType()), Alignment); + Addr = makeNaturalAddressForPointer(Val, T, Alignment); } return MakeAddrLValue(Addr, T, AlignmentSource::Decl); } @@ -3023,11 +3017,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), CapturedStmtInfo->getContextValue()); Address LValueAddress = CapLVal.getAddress(*this); - CapLVal = MakeAddrLValue( - Address(LValueAddress.getPointer(), LValueAddress.getElementType(), - getContext().getDeclAlign(VD)), - CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl), - CapLVal.getTBAAInfo()); + CapLVal = MakeAddrLValue(Address(LValueAddress.emitRawPointer(*this), + LValueAddress.getElementType(), + getContext().getDeclAlign(VD)), + CapLVal.getType(), + LValueBaseInfo(AlignmentSource::Decl), + CapLVal.getTBAAInfo()); // Mark lvalue as nontemporal if the variable is marked as nontemporal // in simd context. if (getLangOpts().OpenMP && @@ -3083,7 +3078,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // Handle threadlocal function locals. if (VD->getTLSKind() != VarDecl::TLS_None) addr = addr.withPointer( - Builder.CreateThreadLocalAddress(addr.getPointer()), NotKnownNonNull); + Builder.CreateThreadLocalAddress(addr.getBasePointer()), + NotKnownNonNull); // Check for OpenMP threadprivate variables. if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && @@ -3351,7 +3347,7 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) { // Pointers are passed directly, everything else is passed by address. if (!V->getType()->isPointerTy()) { - Address Ptr = CreateDefaultAlignTempAlloca(V->getType()); + RawAddress Ptr = CreateDefaultAlignTempAlloca(V->getType()); Builder.CreateStore(V, Ptr); V = Ptr.getPointer(); } @@ -3924,6 +3920,21 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, } } +static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, + ArrayRef indices, + llvm::Type *elementType, bool inbounds, + bool signedIndices, SourceLocation loc, + CharUnits align, + const llvm::Twine &name = "arrayidx") { + if (inbounds) { + return CGF.EmitCheckedInBoundsGEP(addr, indices, elementType, signedIndices, + CodeGenFunction::NotSubtraction, loc, + align, name); + } else { + return CGF.Builder.CreateGEP(addr, indices, elementType, align, name); + } +} + static CharUnits getArrayElementAlign(CharUnits arrayAlign, llvm::Value *idx, CharUnits eltSize) { @@ -3971,7 +3982,7 @@ static Address wrapWithBPFPreserveStaticOffset(CodeGenFunction &CGF, llvm::Function *Fn = CGF.CGM.getIntrinsic(llvm::Intrinsic::preserve_static_offset); - llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.getPointer()}); + llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.emitRawPointer(CGF)}); return Address(Call, Addr.getElementType(), Addr.getAlignment()); } @@ -4034,7 +4045,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, // We can use that to compute the best alignment of the element. CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType); CharUnits eltAlign = - getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); + getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); if (hasBPFPreserveStaticOffset(Base)) addr = wrapWithBPFPreserveStaticOffset(CGF, addr); @@ -4043,19 +4054,19 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, auto LastIndex = dyn_cast(indices.back()); if (!LastIndex || (!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) { - eltPtr = emitArraySubscriptGEP( - CGF, addr.getElementType(), addr.getPointer(), indices, inbounds, - signedIndices, loc, name); + addr = emitArraySubscriptGEP(CGF, addr, indices, + CGF.ConvertTypeForMem(eltType), inbounds, + signedIndices, loc, eltAlign, name); + return addr; } else { // Remember the original array subscript for bpf target unsigned idx = LastIndex->getZExtValue(); llvm::DIType *DbgInfo = nullptr; if (arrayType) DbgInfo = CGF.getDebugInfo()->getOrCreateStandaloneType(*arrayType, loc); - eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getElementType(), - addr.getPointer(), - indices.size() - 1, - idx, DbgInfo); + eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex( + addr.getElementType(), addr.emitRawPointer(CGF), indices.size() - 1, + idx, DbgInfo); } return Address(eltPtr, CGF.ConvertTypeForMem(eltType), eltAlign); @@ -4224,8 +4235,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, CharUnits EltAlign = getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); llvm::Value *EltPtr = - emitArraySubscriptGEP(*this, Int8Ty, Addr.getPointer(), ScaledIdx, - false, SignedIndices, E->getExprLoc()); + emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this), + ScaledIdx, false, SignedIndices, E->getExprLoc()); Addr = Address(EltPtr, OrigBaseElemTy, EltAlign); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the @@ -4271,7 +4282,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, llvm::Type *CountTy = ConvertType(CountFD->getType()); llvm::Value *Res = Builder.CreateInBoundsGEP( - Int8Ty, Addr.getPointer(), + Int8Ty, Addr.emitRawPointer(*this), Builder.getInt32(OffsetDiff.getQuantity()), ".counted_by.gep"); Res = Builder.CreateAlignedLoad(CountTy, Res, getIntAlign(), ".counted_by.load"); @@ -4517,9 +4528,9 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, BaseInfo = ArrayLV.getBaseInfo(); TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); } else { - Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, - TBAAInfo, BaseTy, ResultExprTy, - IsLowerBound); + Address Base = + emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy, + ResultExprTy, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*signedIndices=*/false, E->getExprLoc()); @@ -4606,7 +4617,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { SkippedChecks.set(SanitizerKind::Alignment, true); if (IsBaseCXXThis || isa(BaseExpr)) SkippedChecks.set(SanitizerKind::Null, true); - EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, + EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr, PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); } else @@ -4655,8 +4666,8 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, LambdaLV = EmitLoadOfReferenceLValue(AddrOfExplicitObject, D->getType(), AlignmentSource::Decl); else - LambdaLV = MakeNaturalAlignAddrLValue(AddrOfExplicitObject.getPointer(), - D->getType().getNonReferenceType()); + LambdaLV = MakeAddrLValue(AddrOfExplicitObject, + D->getType().getNonReferenceType()); } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); @@ -4846,7 +4857,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // information provided by invariant.group. This is because accessing // fields may leak the real address of dynamic object, which could result // in miscompilation when leaked pointer would be compared. - auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer()); + auto *stripped = + Builder.CreateStripInvariantGroup(addr.emitRawPointer(*this)); addr = Address(stripped, addr.getElementType(), addr.getAlignment()); } } @@ -4865,10 +4877,11 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // Remember the original union field index llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(base.getType(), rec->getLocation()); - addr = Address( - Builder.CreatePreserveUnionAccessIndex( - addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), - addr.getElementType(), addr.getAlignment()); + addr = + Address(Builder.CreatePreserveUnionAccessIndex( + addr.emitRawPointer(*this), + getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), + addr.getElementType(), addr.getAlignment()); } if (FieldType->isReferenceType()) @@ -5105,11 +5118,9 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue( if (Info.LHS && Info.RHS) { Address lhsAddr = Info.LHS->getAddress(*this); Address rhsAddr = Info.RHS->getAddress(*this); - llvm::PHINode *phi = Builder.CreatePHI(lhsAddr.getType(), 2, "cond-lvalue"); - phi->addIncoming(lhsAddr.getPointer(), Info.lhsBlock); - phi->addIncoming(rhsAddr.getPointer(), Info.rhsBlock); - Address result(phi, lhsAddr.getElementType(), - std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment())); + Address result = mergeAddressesInConditionalExpr( + lhsAddr, rhsAddr, Info.lhsBlock, Info.rhsBlock, + Builder.GetInsertBlock(), expr->getType()); AlignmentSource alignSource = std::max(Info.LHS->getBaseInfo().getAlignmentSource(), Info.RHS->getBaseInfo().getAlignmentSource()); @@ -5196,7 +5207,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { LValue LV = EmitLValue(E->getSubExpr()); Address V = LV.getAddress(*this); const auto *DCE = cast(E); - return MakeNaturalAlignAddrLValue(EmitDynamicCast(V, DCE), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitDynamicCast(V, DCE), E->getType()); } case CK_ConstructorConversion: @@ -5261,8 +5272,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is // performed and the object is not of the derived type. if (sanitizePerformTypeCheck()) - EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), - Derived.getPointer(), E->getType()); + EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), Derived, + E->getType()); if (SanOpts.has(SanitizerKind::CFIDerivedCast)) EmitVTablePtrCheckForCast(E->getType(), Derived, @@ -5618,7 +5629,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { LValue CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) { - return MakeNaturalAlignAddrLValue(EmitCXXTypeidExpr(E), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitCXXTypeidExpr(E), E->getType()); } Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) { diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 5190b22bcc16..143855aa84ca 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -294,10 +294,10 @@ void AggExprEmitter::withReturnValueSlot( // Otherwise, EmitCall will emit its own, notice that it's "unused", and end // its lifetime before we have the chance to emit a proper destructor call. bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() || - (RequiresDestruction && !Dest.getAddress().isValid()); + (RequiresDestruction && Dest.isIgnored()); Address RetAddr = Address::invalid(); - Address RetAllocaAddr = Address::invalid(); + RawAddress RetAllocaAddr = RawAddress::invalid(); EHScopeStack::stable_iterator LifetimeEndBlock; llvm::Value *LifetimeSizePtr = nullptr; @@ -329,7 +329,8 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) return; - assert(Dest.isIgnored() || Dest.getPointer() != Src.getAggregatePointer()); + assert(Dest.isIgnored() || Dest.emitRawPointer(CGF) != + Src.getAggregatePointer(E->getType(), CGF)); EmitFinalDestCopy(E->getType(), Src); if (!RequiresDestruction && LifetimeStartInst) { @@ -448,7 +449,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); llvm::Value *IdxStart[] = { Zero, Zero }; llvm::Value *ArrayStart = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxStart, "arraystart"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxStart, + "arraystart"); CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); ++Field; @@ -465,7 +467,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { // End pointer. llvm::Value *IdxEnd[] = { Zero, Size }; llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxEnd, "arrayend"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd, + "arrayend"); CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { // Length. @@ -516,9 +519,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, // down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = { zero, zero }; - llvm::Value *begin = Builder.CreateInBoundsGEP( - DestPtr.getElementType(), DestPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(DestPtr.getElementType(), + DestPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); CharUnits elementAlign = @@ -1059,7 +1062,7 @@ void AggExprEmitter::VisitBinCmp(const BinaryOperator *E) { if (RV.isScalar()) return {RV.getScalarVal(), nullptr}; if (RV.isAggregate()) - return {RV.getAggregatePointer(), nullptr}; + return {RV.getAggregatePointer(E->getType(), CGF), nullptr}; assert(RV.isComplex()); return RV.getComplexVal(); }; @@ -1818,7 +1821,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // else, clean it up for -O0 builds and general tidiness. if (!pushedCleanup && LV.isSimple()) if (llvm::GetElementPtrInst *GEP = - dyn_cast(LV.getPointer(CGF))) + dyn_cast(LV.emitRawPointer(CGF))) if (GEP->use_empty()) GEP->eraseFromParent(); } @@ -1849,9 +1852,9 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, // destPtr is an array*. Construct an elementType* by drilling down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = {zero, zero}; - llvm::Value *begin = Builder.CreateInBoundsGEP( - destPtr.getElementType(), destPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getElementType(), + destPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); // Prepare to special-case multidimensional array initialization: we avoid // emitting multiple destructor loops in that case. diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 35da0f1a89bc..5c16a48d3ee6 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -280,7 +280,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); - This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); + This = MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(), + BaseInfo, TBAAInfo); } else { This = EmitLValue(Base); } @@ -353,10 +354,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (IsImplicitObjectCXXThis || isa(IOA)) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, - This.getPointer(*this), - C.getRecordType(CalleeDecl->getParent()), - /*Alignment=*/CharUnits::Zero(), SkippedChecks); + EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, This, + C.getRecordType(CalleeDecl->getParent()), SkippedChecks); // C++ [class.virtual]p12: // Explicit qualification with the scope operator (5.1) suppresses the @@ -455,7 +454,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, else This = EmitLValue(BaseExpr, KnownNonNull).getAddress(*this); - EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(), + EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), QualType(MPT->getClass(), 0)); // Get the member function pointer. @@ -1109,9 +1108,10 @@ void CodeGenFunction::EmitNewArrayInitializer( // alloca. EndOfInit = CreateTempAlloca(BeginPtr.getType(), getPointerAlign(), "array.init.end"); - CleanupDominator = Builder.CreateStore(BeginPtr.getPointer(), EndOfInit); - pushIrregularPartialArrayCleanup(BeginPtr.getPointer(), EndOfInit, - ElementType, ElementAlign, + CleanupDominator = + Builder.CreateStore(BeginPtr.emitRawPointer(*this), EndOfInit); + pushIrregularPartialArrayCleanup(BeginPtr.emitRawPointer(*this), + EndOfInit, ElementType, ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); } @@ -1123,16 +1123,17 @@ void CodeGenFunction::EmitNewArrayInitializer( // element. TODO: some of these stores can be trivially // observed to be unnecessary. if (EndOfInit.isValid()) { - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); } // FIXME: If the last initializer is an incomplete initializer list for // an array, and we have an array filler, we can fold together the two // initialization loops. StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr, AggValueSlot::DoesNotOverlap); - CurPtr = Address(Builder.CreateInBoundsGEP( - CurPtr.getElementType(), CurPtr.getPointer(), - Builder.getSize(1), "array.exp.next"), + CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(), + CurPtr.emitRawPointer(*this), + Builder.getSize(1), + "array.exp.next"), CurPtr.getElementType(), StartAlign.alignmentAtOffset((++i) * ElementSize)); } @@ -1186,7 +1187,7 @@ void CodeGenFunction::EmitNewArrayInitializer( // FIXME: Share this cleanup with the constructor call emission rather than // having it create a cleanup of its own. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Emit a constructor call loop to initialize the remaining elements. if (InitListElements) @@ -1249,15 +1250,15 @@ void CodeGenFunction::EmitNewArrayInitializer( llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end"); // Find the end of the array, hoisted out of the loop. - llvm::Value *EndPtr = - Builder.CreateInBoundsGEP(BeginPtr.getElementType(), BeginPtr.getPointer(), - NumElements, "array.end"); + llvm::Value *EndPtr = Builder.CreateInBoundsGEP( + BeginPtr.getElementType(), BeginPtr.emitRawPointer(*this), NumElements, + "array.end"); // If the number of elements isn't constant, we have to now check if there is // anything left to initialize. if (!ConstNum) { - llvm::Value *IsEmpty = - Builder.CreateICmpEQ(CurPtr.getPointer(), EndPtr, "array.isempty"); + llvm::Value *IsEmpty = Builder.CreateICmpEQ(CurPtr.emitRawPointer(*this), + EndPtr, "array.isempty"); Builder.CreateCondBr(IsEmpty, ContBB, LoopBB); } @@ -1267,19 +1268,20 @@ void CodeGenFunction::EmitNewArrayInitializer( // Set up the current-element phi. llvm::PHINode *CurPtrPhi = Builder.CreatePHI(CurPtr.getType(), 2, "array.cur"); - CurPtrPhi->addIncoming(CurPtr.getPointer(), EntryBB); + CurPtrPhi->addIncoming(CurPtr.emitRawPointer(*this), EntryBB); CurPtr = Address(CurPtrPhi, CurPtr.getElementType(), ElementAlign); // Store the new Cleanup position for irregular Cleanups. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Enter a partial-destruction Cleanup if necessary. if (!CleanupDominator && needsEHCleanup(DtorKind)) { - pushRegularPartialArrayCleanup(BeginPtr.getPointer(), CurPtr.getPointer(), - ElementType, ElementAlign, - getDestroyer(DtorKind)); + llvm::Value *BeginPtrRaw = BeginPtr.emitRawPointer(*this); + llvm::Value *CurPtrRaw = CurPtr.emitRawPointer(*this); + pushRegularPartialArrayCleanup(BeginPtrRaw, CurPtrRaw, ElementType, + ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); CleanupDominator = Builder.CreateUnreachable(); } @@ -1295,9 +1297,8 @@ void CodeGenFunction::EmitNewArrayInitializer( } // Advance to the next element by adjusting the pointer type as necessary. - llvm::Value *NextPtr = - Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr.getPointer(), 1, - "array.next"); + llvm::Value *NextPtr = Builder.CreateConstInBoundsGEP1_32( + ElementTy, CurPtr.emitRawPointer(*this), 1, "array.next"); // Check whether we've gotten to the end of the array and, if so, // exit the loop. @@ -1523,14 +1524,9 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, typedef CallDeleteDuringNew DirectCleanup; - DirectCleanup *Cleanup = CGF.EHStack - .pushCleanupWithExtra(EHCleanup, - E->getNumPlacementArgs(), - E->getOperatorDelete(), - NewPtr.getPointer(), - AllocSize, - E->passAlignment(), - AllocAlign); + DirectCleanup *Cleanup = CGF.EHStack.pushCleanupWithExtra( + EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(), + NewPtr.emitRawPointer(CGF), AllocSize, E->passAlignment(), AllocAlign); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { auto &Arg = NewArgs[I + NumNonPlacementArgs]; Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty); @@ -1541,7 +1537,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, // Otherwise, we need to save all this stuff. DominatingValue::saved_type SavedNewPtr = - DominatingValue::save(CGF, RValue::get(NewPtr.getPointer())); + DominatingValue::save(CGF, RValue::get(NewPtr, CGF)); DominatingValue::saved_type SavedAllocSize = DominatingValue::save(CGF, RValue::get(AllocSize)); @@ -1618,14 +1614,14 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // In these cases, discard the computed alignment and use the // formal alignment of the allocated type. if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl) - allocation = allocation.withAlignment(allocAlign); + allocation.setAlignment(allocAlign); // Set up allocatorArgs for the call to operator delete if it's not // the reserved global operator. if (E->getOperatorDelete() && !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType()); - allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType()); + allocatorArgs.add(RValue::get(allocation, *this), arg->getType()); } } else { @@ -1713,8 +1709,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull"); contBB = createBasicBlock("new.cont"); - llvm::Value *isNull = - Builder.CreateIsNull(allocation.getPointer(), "new.isnull"); + llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull"); Builder.CreateCondBr(isNull, contBB, notNullBB); EmitBlock(notNullBB); } @@ -1760,12 +1755,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { SkippedChecks.set(SanitizerKind::Null, nullCheck); EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(), - result.getPointer(), allocType, result.getAlignment(), - SkippedChecks, numElements); + result, allocType, result.getAlignment(), SkippedChecks, + numElements); EmitNewInitializer(*this, E, allocType, elementTy, result, numElements, allocSizeWithoutCookie); - llvm::Value *resultPtr = result.getPointer(); + llvm::Value *resultPtr = result.emitRawPointer(*this); if (E->isArray()) { // NewPtr is a pointer to the base element type. If we're // allocating an array of arrays, we'll need to cast back to the @@ -1909,7 +1904,8 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, Dtor); else - CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType); + CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.emitRawPointer(CGF), + ElementType); } /// Emit the code for deleting a single object. @@ -1925,8 +1921,7 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // dynamic type, the static type shall be a base class of the dynamic type // of the object to be deleted and the static type shall have a virtual // destructor or the behavior is undefined. - CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, - DE->getExprLoc(), Ptr.getPointer(), + CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, DE->getExprLoc(), Ptr, ElementType); const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); @@ -1975,9 +1970,8 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // Make sure that we call delete even if the dtor throws. // This doesn't have to a conditional cleanup because we're going // to pop it off in a second. - CGF.EHStack.pushCleanup(NormalAndEHCleanup, - Ptr.getPointer(), - OperatorDelete, ElementType); + CGF.EHStack.pushCleanup( + NormalAndEHCleanup, Ptr.emitRawPointer(CGF), OperatorDelete, ElementType); if (Dtor) CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, @@ -2064,7 +2058,7 @@ static void EmitArrayDelete(CodeGenFunction &CGF, CharUnits elementAlign = deletedPtr.getAlignment().alignmentOfArrayElement(elementSize); - llvm::Value *arrayBegin = deletedPtr.getPointer(); + llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF); llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP( deletedPtr.getElementType(), arrayBegin, numElements, "delete.end"); @@ -2095,7 +2089,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); - llvm::Value *IsNull = Builder.CreateIsNull(Ptr.getPointer(), "isnull"); + llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull"); Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); @@ -2130,10 +2124,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { GEP.push_back(Zero); } - Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getElementType(), - Ptr.getPointer(), GEP, "del.first"), - ConvertTypeForMem(DeleteTy), Ptr.getAlignment(), - Ptr.isKnownNonNull()); + Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, ConvertTypeForMem(DeleteTy), + Ptr.getAlignment(), "del.first"); } assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); @@ -2191,7 +2183,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, // destruction and the static type of the operand is neither the constructor // or destructor’s class nor one of its bases, the behavior is undefined. CGF.EmitTypeCheck(CodeGenFunction::TCK_DynamicOperation, E->getExprLoc(), - ThisPtr.getPointer(), SrcRecordTy); + ThisPtr, SrcRecordTy); // C++ [expr.typeid]p2: // If the glvalue expression is obtained by applying the unary * operator to @@ -2207,7 +2199,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, CGF.createBasicBlock("typeid.bad_typeid"); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end"); - llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr.getPointer()); + llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr); CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock); CGF.EmitBlock(BadTypeidBlock); @@ -2293,8 +2285,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, // construction or destruction and the static type of the operand is not a // pointer to or object of the constructor or destructor’s own class or one // of its bases, the dynamic_cast results in undefined behavior. - EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr.getPointer(), - SrcRecordTy); + EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr, SrcRecordTy); if (DCE->isAlwaysNull()) { if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy)) { @@ -2329,7 +2320,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, CastNull = createBasicBlock("dynamic_cast.null"); CastNotNull = createBasicBlock("dynamic_cast.notnull"); - llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 67a3cdc77042..36d7493d9a6b 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -800,8 +800,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, // Add a vtable pointer, if we need one and it hasn't already been added. if (Layout.hasOwnVFPtr()) { llvm::Constant *VTableAddressPoint = - CGM.getCXXABI().getVTableAddressPointForConstExpr( - BaseSubobject(CD, Offset), VTableClass); + CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset), + VTableClass); if (!AppendBytes(Offset, VTableAddressPoint)) return false; } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 8536570087ad..83247aa48f86 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2250,7 +2250,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { // performed and the object is not of the derived type. if (CGF.sanitizePerformTypeCheck()) CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(), - Derived.getPointer(), DestTy->getPointeeType()); + Derived, DestTy->getPointeeType()); if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast)) CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived, @@ -2258,13 +2258,14 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { CodeGenFunction::CFITCK_DerivedCast, CE->getBeginLoc()); - return Derived.getPointer(); + return CGF.getAsNaturalPointerTo(Derived, CE->getType()->getPointeeType()); } case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { // The EmitPointerWithAlignment path does this fine; just discard // the alignment. - return CGF.EmitPointerWithAlignment(CE).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitPointerWithAlignment(CE), + CE->getType()->getPointeeType()); } case CK_Dynamic: { @@ -2274,7 +2275,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } case CK_ArrayToPointerDecay: - return CGF.EmitArrayToPointerDecay(E).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitArrayToPointerDecay(E), + CE->getType()->getPointeeType()); case CK_FunctionToPointerDecay: return EmitLValue(E).getPointer(CGF); @@ -5588,3 +5590,16 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr, return GEPVal; } + +Address CodeGenFunction::EmitCheckedInBoundsGEP( + Address Addr, ArrayRef IdxList, llvm::Type *elementType, + bool SignedIndices, bool IsSubtraction, SourceLocation Loc, CharUnits Align, + const Twine &Name) { + if (!SanOpts.has(SanitizerKind::PointerOverflow)) + return Builder.CreateInBoundsGEP(Addr, IdxList, elementType, Align, Name); + + return RawAddress( + EmitCheckedInBoundsGEP(Addr.getElementType(), Addr.emitRawPointer(*this), + IdxList, SignedIndices, IsSubtraction, Loc, Name), + elementType, Align); +} diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 75c1d7fbea84..8fade0fac21e 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -366,7 +366,7 @@ template struct GenFuncBase { llvm::Value *SizeInBytes = CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP( - CGF.Int8Ty, DstAddr.getPointer(), SizeInBytes); + CGF.Int8Ty, DstAddr.emitRawPointer(CGF), SizeInBytes); llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); // Create the header block and insert the phi instructions. @@ -376,7 +376,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); - PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); + PHIs[I]->addIncoming(StartAddrs[I].emitRawPointer(CGF), PreheaderBB); } // Create the exit and loop body blocks. @@ -410,7 +410,7 @@ template struct GenFuncBase { // Instrs to update the destination and source addresses. // Update phi instructions. NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); - PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); + PHIs[I]->addIncoming(NewAddrs[I].emitRawPointer(CGF), LoopBB); } // Insert an unconditional branch to the header block. @@ -488,7 +488,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { Alignments[I] = Addrs[I].getAlignment(); - Ptrs[I] = Addrs[I].getPointer(); + Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF); } if (llvm::Function *F = diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index f3a948cf13f9..c7f497a7c845 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -94,8 +94,8 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { // and cast value to correct type Address Temporary = CreateMemTemp(SubExpr->getType()); EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); - llvm::Value *BitCast = - Builder.CreateBitCast(Temporary.getPointer(), ConvertType(ArgQT)); + llvm::Value *BitCast = Builder.CreateBitCast( + Temporary.emitRawPointer(*this), ConvertType(ArgQT)); Args.add(RValue::get(BitCast), ArgQT); // Create char array to store type encoding @@ -204,11 +204,11 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); const ParmVarDecl *argDecl = *PI++; QualType ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Objects.getPointer()), ArgQT); + Args.add(RValue::get(Objects, *this), ArgQT); if (DLE) { argDecl = *PI++; ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Keys.getPointer()), ArgQT); + Args.add(RValue::get(Keys, *this), ArgQT); } argDecl = *PI; ArgQT = argDecl->getType().getUnqualifiedType(); @@ -827,7 +827,7 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, // sizeof (Type of Ivar), isAtomic, false); CallArgList args; - llvm::Value *dest = CGF.ReturnValue.getPointer(); + llvm::Value *dest = CGF.ReturnValue.emitRawPointer(CGF); args.add(RValue::get(dest), Context.VoidPtrTy); args.add(RValue::get(src), Context.VoidPtrTy); @@ -1147,8 +1147,8 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, callCStructCopyConstructor(Dst, Src); } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), ivar, - AtomicHelperFn); + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), + ivar, AtomicHelperFn); } return; } @@ -1163,7 +1163,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), ivar, AtomicHelperFn); } return; @@ -1287,7 +1287,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { - value = LV.getAddress(*this).getPointer(); + value = LV.getAddress(*this).emitRawPointer(*this); } else { // We want to load and autoreleaseReturnValue ARC __weak ivars. if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { @@ -1821,16 +1821,14 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ CallArgList Args; // The first argument is a temporary of the enumeration-state type. - Args.add(RValue::get(StatePtr.getPointer()), - getContext().getPointerType(StateTy)); + Args.add(RValue::get(StatePtr, *this), getContext().getPointerType(StateTy)); // The second argument is a temporary array with space for NumItems // pointers. We'll actually be loading elements from the array // pointer written into the control state; this buffer is so that // collections that *aren't* backed by arrays can still queue up // batches of elements. - Args.add(RValue::get(ItemsPtr.getPointer()), - getContext().getPointerType(ItemsTy)); + Args.add(RValue::get(ItemsPtr, *this), getContext().getPointerType(ItemsTy)); // The third argument is the capacity of that temporary array. llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType()); @@ -2198,7 +2196,7 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr, if (!fn) fn = getARCIntrinsic(IntID, CGF.CGM); - return CGF.EmitNounwindRuntimeCall(fn, addr.getPointer()); + return CGF.EmitNounwindRuntimeCall(fn, addr.emitRawPointer(CGF)); } /// Perform an operation having the following signature: @@ -2216,9 +2214,8 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr, llvm::Type *origType = value->getType(); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(addr.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy) - }; + CGF.Builder.CreateBitCast(addr.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy)}; llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2237,9 +2234,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src, fn = getARCIntrinsic(IntID, CGF.CGM); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(src.getPointer(), CGF.Int8PtrPtrTy) - }; + CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(src.emitRawPointer(CGF), CGF.Int8PtrPtrTy)}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2490,9 +2486,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr, fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM); llvm::Value *args[] = { - Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy), - Builder.CreateBitCast(value, Int8PtrTy) - }; + Builder.CreateBitCast(addr.emitRawPointer(*this), Int8PtrPtrTy), + Builder.CreateBitCast(value, Int8PtrTy)}; EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2643,7 +2638,7 @@ void CodeGenFunction::EmitARCDestroyWeak(Address addr) { if (!fn) fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM); - EmitNounwindRuntimeCall(fn, addr.getPointer()); + EmitNounwindRuntimeCall(fn, addr.emitRawPointer(*this)); } /// void \@objc_moveWeak(i8** %dest, i8** %src) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index a36b0cdddaf0..4e7f777ba1d9 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -706,7 +706,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd}; + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -761,8 +762,8 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::FunctionCallee LookupFn = SlotLookupFn; // Store the receiver on the stack so that we can reload it later - Address ReceiverPtr = - CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); + RawAddress ReceiverPtr = + CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); Builder.CreateStore(Receiver, ReceiverPtr); llvm::Value *self; @@ -778,9 +779,9 @@ class CGObjCGNUstep : public CGObjCGNU { LookupFn2->addParamAttr(0, llvm::Attribute::NoCapture); llvm::Value *args[] = { - EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy) }; + EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy)}; llvm::CallBase *slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args); slot->setOnlyReadsMemory(); slot->setMetadata(msgSendMDKind, node); @@ -800,7 +801,7 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd}; + llvm::Value *lookupArgs[] = {ObjCSuper.emitRawPointer(CGF), cmd}; llvm::CallInst *slot = CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs); @@ -1221,10 +1222,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { llvm::Value *cmd, MessageSendInfo &MSI) override { // Don't access the slot unless we're trying to cache the result. CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, - ObjCSuper.getPointer(), - PtrToObjCSuperTy), - cmd}; + llvm::Value *lookupArgs[] = { + CGObjCGNU::EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), + PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -2186,7 +2187,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd, + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd, }; if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) @@ -4201,15 +4203,15 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF, Address AddrWeakObj) { CGBuilderTy &B = CGF.Builder; - return B.CreateCall(WeakReadFn, - EnforceType(B, AddrWeakObj.getPointer(), PtrToIdTy)); + return B.CreateCall( + WeakReadFn, EnforceType(B, AddrWeakObj.emitRawPointer(CGF), PtrToIdTy)); } void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(WeakAssignFn, {src, dstVal}); } @@ -4218,7 +4220,7 @@ void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF, bool threadlocal) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); // FIXME. Add threadloca assign API assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI"); B.CreateCall(GlobalAssignFn, {src, dstVal}); @@ -4229,7 +4231,7 @@ void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *ivarOffset) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), IdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), IdTy); B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset}); } @@ -4237,7 +4239,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(StrongCastAssignFn, {src, dstVal}); } @@ -4246,8 +4248,8 @@ void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address SrcPtr, llvm::Value *Size) { CGBuilderTy &B = CGF.Builder; - llvm::Value *DestPtrVal = EnforceType(B, DestPtr.getPointer(), PtrTy); - llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.getPointer(), PtrTy); + llvm::Value *DestPtrVal = EnforceType(B, DestPtr.emitRawPointer(CGF), PtrTy); + llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.emitRawPointer(CGF), PtrTy); B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal, Size}); } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index ed8d7b9a065d..8a599c10e1ca 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1310,7 +1310,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); public: CGObjCMac(CodeGen::CodeGenModule &cgm); @@ -1538,7 +1538,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C /// interface. The return value has type EHTypePtrTy. @@ -2064,9 +2064,8 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, const ObjCMethodDecl *Method) { // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, @@ -4259,7 +4258,7 @@ namespace { CGF.EmitBlock(FinallyCallExit); CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); CGF.EmitBlock(FinallyNoCallExit); @@ -4425,7 +4424,9 @@ void FragileHazards::emitHazardsInNewBlocks() { } static void addIfPresent(llvm::DenseSet &S, Address V) { - if (V.isValid()) S.insert(V.getPointer()); + if (V.isValid()) + if (llvm::Value *Ptr = V.getBasePointer()) + S.insert(Ptr); } void FragileHazards::collectLocals() { @@ -4628,13 +4629,13 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // - Call objc_exception_try_enter to push ExceptionData on top of // the EH stack. CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); // - Call setjmp on the exception data buffer. llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( - ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes, + ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes, "setjmp_buffer"); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); @@ -4673,9 +4674,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, } else { // Retrieve the exception object. We may emit multiple blocks but // nothing can cross this so the value is already in SSA form. - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); // Push the exception to rethrow onto the EH value stack for the // benefit of any @throws in the handlers. @@ -4698,7 +4699,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Enter a new exception try block (in case a @catch block // throws an exception). CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), @@ -4829,9 +4830,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Extract the new exception and save it to the // propagating-exception slot. assert(PropagatingExnVar.isValid()); - llvm::CallInst *NewCaught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *NewCaught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); // Don't pop the catch handler; the throw already did. @@ -4861,9 +4862,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Otherwise, just look in the buffer for the exception to throw. } else { - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer()); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF)); PropagatingExn = Caught; } @@ -4906,7 +4906,7 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, Address AddrWeakObj) { llvm::Type* DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -4928,8 +4928,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = { src, dstVal }; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -4950,8 +4950,8 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), @@ -4977,8 +4977,8 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -4997,8 +4997,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "strongassign"); @@ -5007,7 +5007,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -5243,7 +5244,7 @@ llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel)); } -Address CGObjCMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) { CharUnits Align = CGM.getPointerAlign(); llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; @@ -5254,7 +5255,7 @@ Address CGObjCMac::EmitSelectorAddr(Selector Sel) { Entry->setExternallyInitialized(true); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { @@ -7323,7 +7324,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, ObjCTypes.MessageRefTy, CGF.getPointerAlign()); // Update the message ref argument. - args[1].setRValue(RValue::get(mref.getPointer())); + args[1].setRValue(RValue::get(mref, CGF)); // Load the function to call from the message ref table. Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0); @@ -7552,9 +7553,8 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // ... // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); @@ -7594,7 +7594,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, return LI; } -Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; CharUnits Align = CGM.getPointerAlign(); if (!Entry) { @@ -7610,7 +7610,7 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { CGM.addCompilerUsedGlobal(Entry); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. @@ -7629,8 +7629,8 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -7650,8 +7650,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "weakassign"); @@ -7660,7 +7660,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *Size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), Size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -7672,7 +7673,7 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( Address AddrWeakObj) { llvm::Type *DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -7694,8 +7695,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -7716,8 +7717,8 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 424564f97599..01d0f35da196 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -67,7 +67,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr"); if (!Ivar->isBitField()) { - LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(V, IvarTy); return LV; } @@ -233,7 +233,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI(); if (auto *CPI = dyn_cast_or_null(CPICandidate)) { CGF.CurrentFuncletPad = CPI; - CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); + CPI->setOperand(2, CGF.getExceptionSlot().emitRawPointer(CGF)); CGF.EHStack.pushCleanup(NormalCleanup, CPI); } } @@ -405,7 +405,7 @@ bool CGObjCRuntime::canMessageReceiverBeNull(CodeGenFunction &CGF, auto self = curMethod->getSelfDecl(); if (self->getType().isConstQualified()) { if (auto LI = dyn_cast(receiver->stripPointerCasts())) { - llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).getPointer(); + llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).emitRawPointer(CGF); if (selfAddr == LI->getPointerOperand()) { return false; } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 00e395c2a207..bc363313dec6 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -622,7 +622,7 @@ static void emitInitWithReductionInitializer(CodeGenFunction &CGF, auto *GV = new llvm::GlobalVariable( CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Init, Name); - LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(GV, Ty); RValue InitRVal; switch (CGF.getEvaluationKind(Ty)) { case TEK_Scalar: @@ -668,8 +668,8 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, llvm::Value *SrcBegin = nullptr; if (DRD) - SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + SrcBegin = SrcAddr.emitRawPointer(CGF); + llvm::Value *DestBegin = DestAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -912,7 +912,7 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr) { - Address Tmp = Address::invalid(); + RawAddress Tmp = RawAddress::invalid(); Address TopTmp = Address::invalid(); Address MostTopTmp = Address::invalid(); BaseTy = BaseTy.getNonReferenceType(); @@ -971,10 +971,10 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( SharedAddr.getElementType(), BaseLValue.getPointer(CGF), - SharedAddr.getPointer()); + SharedAddr.emitRawPointer(CGF)); llvm::Value *PrivatePointer = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivateAddr.getPointer(), SharedAddr.getType()); + PrivateAddr.emitRawPointer(CGF), SharedAddr.getType()); llvm::Value *Ptr = CGF.Builder.CreateGEP( SharedAddr.getElementType(), PrivatePointer, Adjustment); return castToBase(CGF, OrigVD->getType(), @@ -1557,7 +1557,7 @@ static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc( return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName); } -Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { +ConstantAddress CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; auto LinkageForVariable = [&VD, this]() { @@ -1579,8 +1579,8 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { LinkageForVariable); if (!addr) - return Address::invalid(); - return Address(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); + return ConstantAddress::invalid(); + return ConstantAddress(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); } llvm::Constant * @@ -1604,7 +1604,7 @@ Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy), + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy), CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), getOrCreateThreadPrivateCache(VD)}; return Address( @@ -1627,7 +1627,8 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit( // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) // to register constructor/destructor for variable. llvm::Value *Args[] = { - OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), + OMPLoc, + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.VoidPtrTy), Ctor, CopyCtor, Dtor}; CGF.EmitRuntimeCall( OMPBuilder.getOrCreateRuntimeFunction( @@ -1900,13 +1901,13 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, // OutlinedFn(>id, &zero_bound, CapturedStruct); Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); - Address ZeroAddrBound = + RawAddress ZeroAddrBound = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".bound.zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddrBound); llvm::SmallVector OutlinedFnArgs; // ThreadId for serialized parallels is 0. - OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); + OutlinedFnArgs.push_back(ThreadIDAddr.emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); @@ -2272,7 +2273,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, emitUpdateLocation(CGF, Loc), // ident_t * getThreadID(CGF, Loc), // i32 BufSize, // size_t - CL.getPointer(), // void * + CL.emitRawPointer(CGF), // void * CpyFn, // void (*) (void *, void *) DidItVal // i32 did_it }; @@ -2591,10 +2592,10 @@ static void emitForStaticInitCall( ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, M2)), // Schedule type - Values.IL.getPointer(), // &isLastIter - Values.LB.getPointer(), // &LB - Values.UB.getPointer(), // &UB - Values.ST.getPointer(), // &Stride + Values.IL.emitRawPointer(CGF), // &isLastIter + Values.LB.emitRawPointer(CGF), // &LB + Values.UB.emitRawPointer(CGF), // &UB + Values.ST.emitRawPointer(CGF), // &Stride CGF.Builder.getIntN(Values.IVSize, 1), // Incr Chunk // Chunk }; @@ -2697,12 +2698,11 @@ llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, // kmp_int[32|64] *p_stride); llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), - IL.getPointer(), // &isLastIter - LB.getPointer(), // &Lower - UB.getPointer(), // &Upper - ST.getPointer() // &Stride + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + IL.emitRawPointer(CGF), // &isLastIter + LB.emitRawPointer(CGF), // &Lower + UB.emitRawPointer(CGF), // &Upper + ST.emitRawPointer(CGF) // &Stride }; llvm::Value *Call = CGF.EmitRuntimeCall( OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args); @@ -3047,7 +3047,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, CGF.Builder .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF), CGF.VoidPtrTy, CGF.Int8Ty) - .getPointer()}; + .emitRawPointer(CGF)}; SmallVector CallArgs(std::begin(CommonArgs), std::end(CommonArgs)); if (isOpenMPTaskLoopDirective(Kind)) { @@ -3574,7 +3574,8 @@ getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); Address UpAddrAddress = UpAddrLVal.getAddress(CGF); llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( - UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); + UpAddrAddress.getElementType(), UpAddrAddress.emitRawPointer(CGF), + /*Idx0=*/1); llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); @@ -3888,8 +3889,9 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Size; std::tie(Addr, Size) = getPointerAndSize(CGF, E); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - LValue Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(AffinitiesArray, Idx), KmpTaskAffinityInfoTy); + LValue Base = + CGF.MakeAddrLValue(CGF.Builder.CreateGEP(CGF, AffinitiesArray, Idx), + KmpTaskAffinityInfoTy); // affs[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); @@ -3910,7 +3912,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); llvm::Value *GTid = getThreadID(CGF, Loc); llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - AffinitiesArray.getPointer(), CGM.VoidPtrTy); + AffinitiesArray.emitRawPointer(CGF), CGM.VoidPtrTy); // FIXME: Emit the function and ignore its result for now unless the // runtime function is properly implemented. (void)CGF.EmitRuntimeCall( @@ -3921,8 +3923,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( NewTask, KmpTaskTWithPrivatesPtrTy); - LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, - KmpTaskTWithPrivatesQTy); + LValue Base = CGF.MakeNaturalAlignRawAddrLValue(NewTaskNewTaskTTy, + KmpTaskTWithPrivatesQTy); LValue TDBase = CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); // Fill the data in the resulting kmp_task_t record. @@ -4047,7 +4049,7 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, CGF.ConvertTypeForMem(KmpDependInfoPtrTy)), KmpDependInfoPtrTy->castAs()); Address DepObjAddr = CGF.Builder.CreateGEP( - Base.getAddress(CGF), + CGF, Base.getAddress(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4097,7 +4099,7 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue &PosLVal = *Pos.get(); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(DependenciesArray, Idx), KmpDependInfoTy); + CGF.Builder.CreateGEP(CGF, DependenciesArray, Idx), KmpDependInfoTy); } // deps[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( @@ -4195,7 +4197,7 @@ void CGOpenMPRuntime::emitDepobjElements(CodeGenFunction &CGF, ElSize, CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - Address DepAddr = CGF.Builder.CreateGEP(DependenciesArray, Pos); + Address DepAddr = CGF.Builder.CreateGEP(CGF, DependenciesArray, Pos); CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); // Increase pos. @@ -4430,7 +4432,7 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), CGF.ConvertTypeForMem(KmpDependInfoTy)); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getElementType(), Addr.getPointer(), + Addr.getElementType(), Addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, CGF.VoidPtrTy); @@ -4460,8 +4462,8 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, Address Begin = Base.getAddress(CGF); // Cast from pointer to array type to pointer to single element. - llvm::Value *End = CGF.Builder.CreateGEP( - Begin.getElementType(), Begin.getPointer(), NumDeps); + llvm::Value *End = CGF.Builder.CreateGEP(Begin.getElementType(), + Begin.emitRawPointer(CGF), NumDeps); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); @@ -4469,7 +4471,7 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, CGF.EmitBlock(BodyBB); llvm::PHINode *ElementPHI = CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); - ElementPHI->addIncoming(Begin.getPointer(), EntryBB); + ElementPHI->addIncoming(Begin.emitRawPointer(CGF), EntryBB); Begin = Begin.withPointer(ElementPHI, KnownNonNull); Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4483,12 +4485,12 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, FlagsLVal); // Shift the address forward by one element. - Address ElementNext = - CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); - ElementPHI->addIncoming(ElementNext.getPointer(), - CGF.Builder.GetInsertBlock()); + llvm::Value *ElementNext = + CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext") + .emitRawPointer(CGF); + ElementPHI->addIncoming(ElementNext, CGF.Builder.GetInsertBlock()); llvm::Value *IsEmpty = - CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); + CGF.Builder.CreateICmpEQ(ElementNext, End, "omp.isempty"); CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); // Done. CGF.EmitBlock(DoneBB, /*IsFinished=*/true); @@ -4531,7 +4533,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepTaskArgs[1] = ThreadID; DepTaskArgs[2] = NewTask; DepTaskArgs[3] = NumOfElements; - DepTaskArgs[4] = DependenciesArray.getPointer(); + DepTaskArgs[4] = DependenciesArray.emitRawPointer(CGF); DepTaskArgs[5] = CGF.Builder.getInt32(0); DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); } @@ -4563,7 +4565,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -4725,8 +4727,8 @@ static void EmitOMPAggregateReduction( const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); - llvm::Value *RHSBegin = RHSAddr.getPointer(); - llvm::Value *LHSBegin = LHSAddr.getPointer(); + llvm::Value *RHSBegin = RHSAddr.emitRawPointer(CGF); + llvm::Value *LHSBegin = LHSAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); @@ -4990,7 +4992,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, QualType ReductionArrayTy = C.getConstantArrayType( C.VoidPtrTy, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); const auto *IPriv = Privates.begin(); unsigned Idx = 0; @@ -5462,7 +5464,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( C.getConstantArrayType(RDType, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); // kmp_task_red_input_t .rd_input.[Size]; - Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); + RawAddress TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, Data.ReductionCopies, Data.ReductionOps); for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { @@ -5473,7 +5475,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( TaskRedInput.getElementType(), TaskRedInput.getPointer(), Idxs, /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, ".rd_input.gep."); - LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); + LValue ElemLVal = CGF.MakeNaturalAlignRawAddrLValue(GEP, RDType); // ElemLVal.reduce_shar = &Shareds[Cnt]; LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); RCG.emitSharedOrigLValue(CGF, Cnt); @@ -5629,7 +5631,7 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -5852,7 +5854,7 @@ void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, AllocatorTraitsLVal.getBaseInfo(), AllocatorTraitsLVal.getTBAAInfo()); - llvm::Value *Traits = Addr.getPointer(); + llvm::Value *Traits = Addr.emitRawPointer(CGF); llvm::Value *AllocatorVal = CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -7312,17 +7314,19 @@ private: CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) .getAddress(CGF); } - Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, ComponentLB.getPointer(), LB.getPointer()); + llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); + Size = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, + LBPtr); break; } } assert(Size && "Failed to determine structure size"); CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7332,13 +7336,14 @@ private: LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); } CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).getPointer(), - LB.getPointer()); + CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF), + LBPtr); CombinedInfo.Sizes.push_back( CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7356,20 +7361,21 @@ private: (Next == CE && MapType != OMPC_MAP_unknown)) { if (!IsMappingWholeStruct) { CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1); } else { StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - StructBaseCombinedInfo.BasePointers.push_back(BP.getPointer()); + StructBaseCombinedInfo.BasePointers.push_back( + BP.emitRawPointer(CGF)); StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr); StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - StructBaseCombinedInfo.Pointers.push_back(LB.getPointer()); + StructBaseCombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); StructBaseCombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); StructBaseCombinedInfo.NonContigInfo.Dims.push_back( @@ -8211,11 +8217,11 @@ public: } CombinedInfo.Exprs.push_back(VD); // Base is the base of the struct - CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); // Pointer is the address of the lowest element - llvm::Value *LB = LBAddr.getPointer(); + llvm::Value *LB = LBAddr.emitRawPointer(CGF); const CXXMethodDecl *MD = CGF.CurFuncDecl ? dyn_cast(CGF.CurFuncDecl) : nullptr; const CXXRecordDecl *RD = MD ? MD->getParent() : nullptr; @@ -8229,7 +8235,7 @@ public: // if the this[:1] expression had appeared in a map clause with a map-type // of tofrom. // Emit this[:1] - CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); QualType Ty = MD->getFunctionObjectParameterType(); llvm::Value *Size = CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty, @@ -8238,7 +8244,7 @@ public: } else { CombinedInfo.Pointers.push_back(LB); // Size is (addr of {highest+1} element) - (addr of lowest element) - llvm::Value *HB = HBAddr.getPointer(); + llvm::Value *HB = HBAddr.emitRawPointer(CGF); llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32( HBAddr.getElementType(), HB, /*Idx0=*/1); llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); @@ -8747,7 +8753,7 @@ public: Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( CV, ElementType, CGF.getContext().getDeclAlign(VD), AlignmentSource::Decl)); - CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); + CombinedInfo.Pointers.push_back(PtrAddr.emitRawPointer(CGF)); } else { CombinedInfo.Pointers.push_back(CV); } @@ -9558,10 +9564,11 @@ static void emitTargetCallKernelLaunch( bool HasNoWait = D.hasClausesOfKind(); unsigned NumTargetItems = InputInfo.NumberOfTargetItems; - llvm::Value *BasePointersArray = InputInfo.BasePointersArray.getPointer(); - llvm::Value *PointersArray = InputInfo.PointersArray.getPointer(); - llvm::Value *SizesArray = InputInfo.SizesArray.getPointer(); - llvm::Value *MappersArray = InputInfo.MappersArray.getPointer(); + llvm::Value *BasePointersArray = + InputInfo.BasePointersArray.emitRawPointer(CGF); + llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF); + llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF); + llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF); auto &&EmitTargetCallFallbackCB = [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS, @@ -10309,15 +10316,16 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( // Source location for the ident struct llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); - llvm::Value *OffloadingArgs[] = {RTLoc, - DeviceID, - PointerNum, - InputInfo.BasePointersArray.getPointer(), - InputInfo.PointersArray.getPointer(), - InputInfo.SizesArray.getPointer(), - MapTypesArray, - MapNamesArray, - InputInfo.MappersArray.getPointer()}; + llvm::Value *OffloadingArgs[] = { + RTLoc, + DeviceID, + PointerNum, + InputInfo.BasePointersArray.emitRawPointer(CGF), + InputInfo.PointersArray.emitRawPointer(CGF), + InputInfo.SizesArray.emitRawPointer(CGF), + MapTypesArray, + MapNamesArray, + InputInfo.MappersArray.emitRawPointer(CGF)}; // Select the right runtime function call for each standalone // directive. @@ -11128,7 +11136,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, getThreadID(CGF, D.getBeginLoc()), llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), + CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).emitRawPointer(CGF), CGM.VoidPtrTy)}; llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( @@ -11162,7 +11170,8 @@ static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, /*Volatile=*/false, Int64Ty); } llvm::Value *Args[] = { - ULoc, ThreadID, CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; + ULoc, ThreadID, + CGF.Builder.CreateConstArrayGEP(CntAddr, 0).emitRawPointer(CGF)}; llvm::FunctionCallee RTLFn; llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); OMPDoacrossKind ODK; @@ -11332,7 +11341,7 @@ Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( CGF, SourceLocation::getFromRawEncoding(LocEncoding)); Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - Addr.getPointer(), CGF.VoidPtrTy); + Addr.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *AllocVal = getAllocatorVal(CGF, AllocExpr); Args[2] = AllocVal; CGF.EmitRuntimeCall(RTLFn, Args); @@ -11690,15 +11699,17 @@ void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LLIVTy, getName({UniqueDeclName, "iv"})); cast(LastIV)->setAlignment( IVLVal.getAlignment().getAsAlign()); - LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); + LValue LastIVLVal = + CGF.MakeNaturalAlignRawAddrLValue(LastIV, IVLVal.getType()); // Last value of the lastprivate conditional. // decltype(priv_a) last_a; llvm::GlobalVariable *Last = OMPBuilder.getOrCreateInternalVariable( CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); - Last->setAlignment(LVal.getAlignment().getAsAlign()); - LValue LastLVal = CGF.MakeAddrLValue( - Address(Last, Last->getValueType(), LVal.getAlignment()), LVal.getType()); + cast(Last)->setAlignment( + LVal.getAlignment().getAsAlign()); + LValue LastLVal = + CGF.MakeRawAddrLValue(Last, LVal.getType(), LVal.getAlignment()); // Global loop counter. Required to handle inner parallel-for regions. // iv @@ -11871,9 +11882,8 @@ void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( // The variable was not updated in the region - exit. if (!GV) return; - LValue LPLVal = CGF.MakeAddrLValue( - Address(GV, GV->getValueType(), PrivLVal.getAlignment()), - PrivLVal.getType().getNonReferenceType()); + LValue LPLVal = CGF.MakeRawAddrLValue( + GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); CGF.EmitStoreOfScalar(Res, PrivLVal); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index c3206427b143..522ae3d35d22 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1068,13 +1068,12 @@ public: /// \param Loc Location of the reference to threadprivate var. /// \return Address of the threadprivate variable for the current thread. virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, - Address VDAddr, + const VarDecl *VD, Address VDAddr, SourceLocation Loc); /// Returns the address of the variable marked as declare target with link /// clause OR as declare target with to clause and unified memory. - virtual Address getAddrOfDeclareTargetVar(const VarDecl *VD); + virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD); /// Emit a code for initialization of threadprivate variable. It emits /// a call to runtime library which adds initial value to the newly created diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 299ee1460b3d..5baac8f0e3e2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -1096,7 +1096,8 @@ void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, llvm::PointerType *VarPtrTy = CGF.ConvertTypeForMem(VarTy)->getPointerTo(); llvm::Value *CastedVoidPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( VoidPtr, VarPtrTy, VD->getName() + "_on_stack"); - LValue VarAddr = CGF.MakeNaturalAlignAddrLValue(CastedVoidPtr, VarTy); + LValue VarAddr = + CGF.MakeNaturalAlignPointeeRawAddrLValue(CastedVoidPtr, VarTy); Rec.second.PrivateAddr = VarAddr.getAddress(CGF); Rec.second.GlobalizedVal = VoidPtr; @@ -1206,8 +1207,8 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, bool IsBareKernel = D.getSingleClause(); - Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, - /*Name=*/".zero.addr"); + RawAddress ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, + /*Name=*/".zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddr); llvm::SmallVector OutlinedFnArgs; // We don't emit any thread id function call in bare kernel, but because the @@ -1215,7 +1216,7 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, if (IsBareKernel) OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); else - OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); + OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); @@ -1289,7 +1290,7 @@ void CGOpenMPRuntimeGPU::emitParallelCall(CodeGenFunction &CGF, llvm::ConstantInt::get(CGF.Int32Ty, -1), FnPtr, ID, - Bld.CreateBitOrPointerCast(CapturedVarsAddrs.getPointer(), + Bld.CreateBitOrPointerCast(CapturedVarsAddrs.emitRawPointer(CGF), CGF.VoidPtrPtrTy), llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())}; CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -1503,17 +1504,18 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, CGF.EmitBlock(PreCondBB); llvm::PHINode *PhiSrc = Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2); - PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB); + PhiSrc->addIncoming(Ptr.emitRawPointer(CGF), CurrentBB); llvm::PHINode *PhiDest = Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2); - PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB); + PhiDest->addIncoming(ElemPtr.emitRawPointer(CGF), CurrentBB); Ptr = Address(PhiSrc, Ptr.getElementType(), Ptr.getAlignment()); ElemPtr = Address(PhiDest, ElemPtr.getElementType(), ElemPtr.getAlignment()); + llvm::Value *PtrEndRaw = PtrEnd.emitRawPointer(CGF); + llvm::Value *PtrRaw = Ptr.emitRawPointer(CGF); llvm::Value *PtrDiff = Bld.CreatePtrDiff( - CGF.Int8Ty, PtrEnd.getPointer(), - Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr.getPointer(), - CGF.VoidPtrTy)); + CGF.Int8Ty, PtrEndRaw, + Bld.CreatePointerBitCastOrAddrSpaceCast(PtrRaw, CGF.VoidPtrTy)); Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)), ThenBB, ExitBB); CGF.EmitBlock(ThenBB); @@ -1528,8 +1530,8 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, TBAAAccessInfo()); Address LocalPtr = Bld.CreateConstGEP(Ptr, 1); Address LocalElemPtr = Bld.CreateConstGEP(ElemPtr, 1); - PhiSrc->addIncoming(LocalPtr.getPointer(), ThenBB); - PhiDest->addIncoming(LocalElemPtr.getPointer(), ThenBB); + PhiSrc->addIncoming(LocalPtr.emitRawPointer(CGF), ThenBB); + PhiDest->addIncoming(LocalElemPtr.emitRawPointer(CGF), ThenBB); CGF.EmitBranch(PreCondBB); CGF.EmitBlock(ExitBB); } else { @@ -1676,10 +1678,10 @@ static void emitReductionListCopy( // scope and that of functions it invokes (i.e., reduce_function). // RemoteReduceData[i] = (void*)&RemoteElem if (UpdateDestListPtr) { - CGF.EmitStoreOfScalar(Bld.CreatePointerBitCastOrAddrSpaceCast( - DestElementAddr.getPointer(), CGF.VoidPtrTy), - DestElementPtrAddr, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar( + Bld.CreatePointerBitCastOrAddrSpaceCast( + DestElementAddr.emitRawPointer(CGF), CGF.VoidPtrTy), + DestElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy); } ++Idx; @@ -1830,7 +1832,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, // elemptr = ((CopyType*)(elemptrptr)) + I Address ElemPtr(ElemPtrPtr, CopyType, Align); if (NumIters > 1) - ElemPtr = Bld.CreateGEP(ElemPtr, Cnt); + ElemPtr = Bld.CreateGEP(CGF, ElemPtr, Cnt); // Get pointer to location in transfer medium. // MediumPtr = &medium[warp_id] @@ -1894,7 +1896,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, Loc); Address TargetElemPtr(TargetElemPtrVal, CopyType, Align); if (NumIters > 1) - TargetElemPtr = Bld.CreateGEP(TargetElemPtr, Cnt); + TargetElemPtr = Bld.CreateGEP(CGF, TargetElemPtr, Cnt); // *TargetElemPtr = SrcMediumVal; llvm::Value *SrcMediumValue = @@ -2105,9 +2107,9 @@ static llvm::Function *emitShuffleAndReduceFunction( CGF.EmitBlock(ThenBB); // reduce_function(LocalReduceList, RemoteReduceList) llvm::Value *LocalReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - LocalReduceList.getPointer(), CGF.VoidPtrTy); + LocalReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *RemoteReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - RemoteReduceList.getPointer(), CGF.VoidPtrTy); + RemoteReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); CGM.getOpenMPRuntime().emitOutlinedFunctionCall( CGF, Loc, ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr}); Bld.CreateBr(MergeBB); @@ -2218,9 +2220,9 @@ static llvm::Value *emitListToGlobalCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2304,7 +2306,7 @@ static llvm::Value *emitListToGlobalReduceFunction( // 1. Build a list of reduction variables. // void *RedList[] = {[0], ..., [-1]}; - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); auto IPriv = Privates.begin(); llvm::Value *Idxs[] = {CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(&IdxArg), @@ -2319,10 +2321,10 @@ static llvm::Value *emitListToGlobalReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2425,9 +2427,9 @@ static llvm::Value *emitGlobalToListCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2526,10 +2528,10 @@ static llvm::Value *emitGlobalToListReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2545,7 +2547,7 @@ static llvm::Value *emitGlobalToListReduceFunction( } // Call reduce_function(ReduceList, GlobalReduceList) - llvm::Value *GlobalReduceList = ReductionList.getPointer(); + llvm::Value *GlobalReduceList = ReductionList.emitRawPointer(CGF); Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg); llvm::Value *ReducedPtr = CGF.EmitLoadOfScalar( AddrReduceListArg, /*Volatile=*/false, C.VoidPtrTy, Loc); @@ -2876,7 +2878,7 @@ void CGOpenMPRuntimeGPU::emitReduction( } llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - ReductionList.getPointer(), CGF.VoidPtrTy); + ReductionList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Function *ReductionFn = emitReductionFunction( CGF.CurFn->getName(), Loc, CGF.ConvertTypeForMem(ReductionArrayTy), Privates, LHSExprs, RHSExprs, ReductionOps); @@ -3106,15 +3108,15 @@ llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper( // Get the array of arguments. SmallVector Args; - Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer()); - Args.emplace_back(ZeroAddr.getPointer()); + Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).emitRawPointer(CGF)); + Args.emplace_back(ZeroAddr.emitRawPointer(CGF)); CGBuilderTy &Bld = CGF.Builder; auto CI = CS.capture_begin(); // Use global memory for data sharing. // Handle passing of global args to workers. - Address GlobalArgs = + RawAddress GlobalArgs = CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args"); llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer(); llvm::Value *DataSharingArgs[] = {GlobalArgsPtr}; @@ -3400,7 +3402,7 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas( VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType().getCanonicalType()) .getAddress(CGF); - CGF.EmitStoreOfScalar(VDAddr.getPointer(), VarLVal); + CGF.EmitStoreOfScalar(VDAddr.emitRawPointer(CGF), VarLVal); } } } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index cb5a004e4f4a..576fe2f7a2d4 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2294,7 +2294,7 @@ std::pair CodeGenFunction::EmitAsmInputLValue( Address Addr = InputValue.getAddress(*this); ConstraintStr += '*'; - return {Addr.getPointer(), Addr.getElementType()}; + return {InputValue.getPointer(*this), Addr.getElementType()}; } std::pair @@ -2701,7 +2701,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { ArgTypes.push_back(DestAddr.getType()); ArgElemTypes.push_back(DestAddr.getElementType()); - Args.push_back(DestAddr.getPointer()); + Args.push_back(DestAddr.emitRawPointer(*this)); Constraints += "=*"; Constraints += OutputConstraint; ReadOnly = ReadNone = false; @@ -3076,8 +3076,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr)); // Initialize variable-length arrays. - LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), - Ctx.getTagDeclType(RD)); + LValue Base = MakeNaturalAlignRawAddrLValue( + CapturedStmtInfo->getContextValue(), Ctx.getTagDeclType(RD)); for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType()) { auto *ExprArg = diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f37ac549d10a..e6d504bcdeca 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -350,7 +350,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); llvm::Value *SrcAddrVal = EmitScalarConversion( - DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), + DstAddr.emitRawPointer(*this), + Ctx.getPointerType(Ctx.getUIntPtrType()), Ctx.getPointerType(CurField->getType()), CurCap->getLocation()); LValue SrcLV = MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); @@ -364,7 +365,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( CapturedVars.push_back(CV); } else { assert(CurCap->capturesVariable() && "Expected capture by reference."); - CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer()); + CapturedVars.push_back( + EmitLValue(*I).getAddress(*this).emitRawPointer(*this)); } } } @@ -375,8 +377,9 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, ASTContext &Ctx = CGF.getContext(); llvm::Value *CastedPtr = CGF.EmitScalarConversion( - AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(), + AddrLV.getAddress(CGF).emitRawPointer(CGF), Ctx.getUIntPtrType(), Ctx.getPointerType(DstType), Loc); + // FIXME: should the pointee type (DstType) be passed? Address TmpAddr = CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress(CGF); return TmpAddr; @@ -702,8 +705,8 @@ void CodeGenFunction::EmitOMPAggregateAssign( llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); SrcAddr = SrcAddr.withElementType(DestAddr.getElementType()); - llvm::Value *SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + llvm::Value *SrcBegin = SrcAddr.emitRawPointer(*this); + llvm::Value *DestBegin = DestAddr.emitRawPointer(*this); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = Builder.CreateInBoundsGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -1007,10 +1010,10 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { CopyBegin = createBasicBlock("copyin.not.master"); CopyEnd = createBasicBlock("copyin.not.master.end"); // TODO: Avoid ptrtoint conversion. - auto *MasterAddrInt = - Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy); - auto *PrivateAddrInt = - Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy); + auto *MasterAddrInt = Builder.CreatePtrToInt( + MasterAddr.emitRawPointer(*this), CGM.IntPtrTy); + auto *PrivateAddrInt = Builder.CreatePtrToInt( + PrivateAddr.emitRawPointer(*this), CGM.IntPtrTy); Builder.CreateCondBr( Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin, CopyEnd); @@ -1666,7 +1669,7 @@ Address CodeGenFunction::OMPBuilderCBHelpers::getAddrOfThreadPrivate( llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Data = - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy); + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy); llvm::ConstantInt *Size = CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)); std::string Suffix = getNameWithSeparators({"cache", ""}); llvm::Twine CacheName = Twine(CGM.getMangledName(VD)).concat(Suffix); @@ -2045,7 +2048,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { ->getParam(0) ->getType() .getNonReferenceType(); - Address CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); + RawAddress CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()}); llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count"); @@ -2061,7 +2064,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { LValue LCVal = EmitLValue(LoopVarRef); Address LoopVarAddress = LCVal.getAddress(*this); emitCapturedStmtCall(*this, LoopVarClosure, - {LoopVarAddress.getPointer(), IndVar}); + {LoopVarAddress.emitRawPointer(*this), IndVar}); RunCleanupsScope BodyScope(*this); EmitStmt(BodyStmt); @@ -4795,7 +4798,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.PrivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); CallArgs.push_back(PrivatePtr.getPointer()); @@ -4803,7 +4806,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4813,7 +4816,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.LastprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".lastpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4826,7 +4829,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( Ty = CGF.getContext().getPointerType(Ty); if (isAllocatableDecl(VD)) Ty = CGF.getContext().getPointerType(Ty); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(Ty), ".local.ptr.addr"); auto Result = UntiedLocalVars.insert( std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid()))); @@ -4859,7 +4862,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( if (auto *DI = CGF.getDebugInfo()) if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo()) (void)DI->EmitDeclareOfAutoVariable( - Pair.first, Pair.second.getPointer(), CGF.Builder, + Pair.first, Pair.second.getBasePointer(), CGF.Builder, /*UsePointerValue*/ true); } // Adjust mapping for internal locals by mapping actual memory instead of @@ -4912,14 +4915,14 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -4970,7 +4973,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5089,7 +5092,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( // If there is no user-defined mapper, the mapper array will be nullptr. In // this case, we don't need to privatize it. if (!isa_and_nonnull( - InputInfo.MappersArray.getPointer())) { + InputInfo.MappersArray.emitRawPointer(*this))) { MVD = createImplicitFirstprivateForType( getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc()); TargetScope.addPrivate(MVD, InputInfo.MappersArray); @@ -5115,7 +5118,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -5194,14 +5197,14 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -5247,7 +5250,7 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5394,7 +5397,7 @@ void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) { Dependencies.DepExprs.append(DC->varlist_begin(), DC->varlist_end()); Address DepAddr = CGM.getOpenMPRuntime().emitDepobjDependClause( *this, Dependencies, DC->getBeginLoc()); - EmitStoreOfScalar(DepAddr.getPointer(), DOLVal); + EmitStoreOfScalar(DepAddr.emitRawPointer(*this), DOLVal); return; } if (const auto *DC = S.getSingleClause()) { @@ -6471,21 +6474,21 @@ static void emitOMPAtomicCompareExpr( D->getType()->hasSignedIntegerRepresentation()); llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{ - XAddr.getPointer(), XAddr.getElementType(), + XAddr.emitRawPointer(CGF), XAddr.getElementType(), X->getType()->hasSignedIntegerRepresentation(), X->getType().isVolatileQualified()}; llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal; if (V) { LValue LV = CGF.EmitLValue(V); Address Addr = LV.getAddress(CGF); - VOpVal = {Addr.getPointer(), Addr.getElementType(), + VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), V->getType()->hasSignedIntegerRepresentation(), V->getType().isVolatileQualified()}; } if (R) { LValue LV = CGF.EmitLValue(R); Address Addr = LV.getAddress(CGF); - ROpVal = {Addr.getPointer(), Addr.getElementType(), + ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), R->getType()->hasSignedIntegerRepresentation(), R->getType().isVolatileQualified()}; } @@ -7029,7 +7032,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) { std::tie(NumDependences, DependenciesArray) = CGM.getOpenMPRuntime().emitDependClause(*this, Data.Dependences, S.getBeginLoc()); - DependenceList = DependenciesArray.getPointer(); + DependenceList = DependenciesArray.emitRawPointer(*this); } Data.HasNowaitClause = S.hasClausesOfKind(); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 8dee3f74b44b..862369ae009f 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -201,14 +201,13 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, // Find the first store of "this", which will be to the alloca associated // with "this". - Address ThisPtr = - Address(&*AI, ConvertTypeForMem(MD->getFunctionObjectParameterType()), - CGM.getClassPointerAlignment(MD->getParent())); + Address ThisPtr = makeNaturalAddressForPointer( + &*AI, MD->getFunctionObjectParameterType(), + CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = llvm::find_if(*EntryBB, [&](llvm::Instruction &I) { - return isa(I) && - I.getOperand(0) == ThisPtr.getPointer(); + return isa(I) && I.getOperand(0) == &*AI; }); assert(ThisStore != EntryBB->end() && "Store of this should be in entry block?"); diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index 1e6f67250583..cc9ad10ae596 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -14,12 +14,13 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H +#include "Address.h" +#include "CodeGenTBAA.h" +#include "EHScopeStack.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" -#include "llvm/IR/Value.h" #include "llvm/IR/Type.h" -#include "Address.h" -#include "CodeGenTBAA.h" +#include "llvm/IR/Value.h" namespace llvm { class Constant; @@ -28,57 +29,64 @@ namespace llvm { namespace clang { namespace CodeGen { - class AggValueSlot; - class CodeGenFunction; - struct CGBitFieldInfo; +class AggValueSlot; +class CGBuilderTy; +class CodeGenFunction; +struct CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an /// expression that is evaluated. It can be one of three things: either a /// simple LLVM SSA value, a pair of SSA values for complex numbers, or the /// address of an aggregate value in memory. class RValue { - enum Flavor { Scalar, Complex, Aggregate }; + friend struct DominatingValue; - // The shift to make to an aggregate's alignment to make it look - // like a pointer. - enum { AggAlignShift = 4 }; + enum FlavorEnum { Scalar, Complex, Aggregate }; - // Stores first value and flavor. - llvm::PointerIntPair V1; - // Stores second value and volatility. - llvm::PointerIntPair V2; - // Stores element type for aggregate values. - llvm::Type *ElementType; + union { + // Stores first and second value. + struct { + llvm::Value *first; + llvm::Value *second; + } Vals; + + // Stores aggregate address. + Address AggregateAddr; + }; + + unsigned IsVolatile : 1; + unsigned Flavor : 2; public: - bool isScalar() const { return V1.getInt() == Scalar; } - bool isComplex() const { return V1.getInt() == Complex; } - bool isAggregate() const { return V1.getInt() == Aggregate; } + RValue() : Vals{nullptr, nullptr}, Flavor(Scalar) {} + + bool isScalar() const { return Flavor == Scalar; } + bool isComplex() const { return Flavor == Complex; } + bool isAggregate() const { return Flavor == Aggregate; } - bool isVolatileQualified() const { return V2.getInt(); } + bool isVolatileQualified() const { return IsVolatile; } /// getScalarVal() - Return the Value* of this scalar value. llvm::Value *getScalarVal() const { assert(isScalar() && "Not a scalar!"); - return V1.getPointer(); + return Vals.first; } /// getComplexVal - Return the real/imag components of this complex value. /// std::pair getComplexVal() const { - return std::make_pair(V1.getPointer(), V2.getPointer()); + return std::make_pair(Vals.first, Vals.second); } /// getAggregateAddr() - Return the Value* of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); - auto align = reinterpret_cast(V2.getPointer()) >> AggAlignShift; - return Address( - V1.getPointer(), ElementType, CharUnits::fromQuantity(align)); + return AggregateAddr; } - llvm::Value *getAggregatePointer() const { - assert(isAggregate() && "Not an aggregate!"); - return V1.getPointer(); + + llvm::Value *getAggregatePointer(QualType PointeeType, + CodeGenFunction &CGF) const { + return getAggregateAddress().getBasePointer(); } static RValue getIgnored() { @@ -88,17 +96,19 @@ public: static RValue get(llvm::Value *V) { RValue ER; - ER.V1.setPointer(V); - ER.V1.setInt(Scalar); - ER.V2.setInt(false); + ER.Vals.first = V; + ER.Flavor = Scalar; + ER.IsVolatile = false; return ER; } + static RValue get(Address Addr, CodeGenFunction &CGF) { + return RValue::get(Addr.emitRawPointer(CGF)); + } static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { RValue ER; - ER.V1.setPointer(V1); - ER.V2.setPointer(V2); - ER.V1.setInt(Complex); - ER.V2.setInt(false); + ER.Vals = {V1, V2}; + ER.Flavor = Complex; + ER.IsVolatile = false; return ER; } static RValue getComplex(const std::pair &C) { @@ -107,15 +117,15 @@ public: // FIXME: Aggregate rvalues need to retain information about whether they are // volatile or not. Remove default to find all places that probably get this // wrong. + + /// Convert an Address to an RValue. If the Address is not + /// signed, create an RValue using the unsigned address. Otherwise, resign the + /// address using the provided type. static RValue getAggregate(Address addr, bool isVolatile = false) { RValue ER; - ER.V1.setPointer(addr.getPointer()); - ER.V1.setInt(Aggregate); - ER.ElementType = addr.getElementType(); - - auto align = static_cast(addr.getAlignment().getQuantity()); - ER.V2.setPointer(reinterpret_cast(align << AggAlignShift)); - ER.V2.setInt(isVolatile); + ER.AggregateAddr = addr; + ER.Flavor = Aggregate; + ER.IsVolatile = isVolatile; return ER; } }; @@ -178,8 +188,10 @@ class LValue { MatrixElt // This is a matrix element, use getVector* } LVType; - llvm::Value *V; - llvm::Type *ElementType; + union { + Address Addr = Address::invalid(); + llvm::Value *V; + }; union { // Index into a vector subscript: V[i] @@ -197,10 +209,6 @@ class LValue { // 'const' is unused here Qualifiers Quals; - // The alignment to use when accessing this lvalue. (For vector elements, - // this is the alignment of the whole vector.) - unsigned Alignment; - // objective-c's ivar bool Ivar:1; @@ -234,23 +242,19 @@ class LValue { Expr *BaseIvarExp; private: - void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, + void Initialize(QualType Type, Qualifiers Quals, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - assert((!Alignment.isZero() || Type->isIncompleteType()) && - "initializing l-value with zero alignment!"); - if (isGlobalReg()) - assert(ElementType == nullptr && "Global reg does not store elem type"); - else - assert(ElementType != nullptr && "Must have elem type"); - this->Type = Type; this->Quals = Quals; const unsigned MaxAlign = 1U << 31; - this->Alignment = Alignment.getQuantity() <= MaxAlign - ? Alignment.getQuantity() - : MaxAlign; - assert(this->Alignment == Alignment.getQuantity() && - "Alignment exceeds allowed max!"); + CharUnits Alignment = Addr.getAlignment(); + assert((isGlobalReg() || !Alignment.isZero() || Type->isIncompleteType()) && + "initializing l-value with zero alignment!"); + if (Alignment.getQuantity() > MaxAlign) { + assert(false && "Alignment exceeds allowed max!"); + Alignment = CharUnits::fromQuantity(MaxAlign); + } + this->Addr = Addr; this->BaseInfo = BaseInfo; this->TBAAInfo = TBAAInfo; @@ -259,9 +263,20 @@ private: this->ImpreciseLifetime = false; this->Nontemporal = false; this->ThreadLocalRef = false; + this->IsKnownNonNull = false; this->BaseIvarExp = nullptr; } + void initializeSimpleLValue(Address Addr, QualType Type, + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, + ASTContext &Context) { + Qualifiers QS = Type.getQualifiers(); + QS.setObjCGCAttr(Context.getObjCGCAttrKind(Type)); + LVType = Simple; + Initialize(Type, QS, Addr, BaseInfo, TBAAInfo); + assert(Addr.getBasePointer()->getType()->isPointerTy()); + } + public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } @@ -328,8 +343,8 @@ public: LangAS getAddressSpace() const { return Quals.getAddressSpace(); } - CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } - void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } + CharUnits getAlignment() const { return Addr.getAlignment(); } + void setAlignment(CharUnits A) { Addr.setAlignment(A); } LValueBaseInfo getBaseInfo() const { return BaseInfo; } void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } @@ -345,28 +360,32 @@ public: // simple lvalue llvm::Value *getPointer(CodeGenFunction &CGF) const { assert(isSimple()); - return V; + return Addr.getBasePointer(); } - Address getAddress(CodeGenFunction &CGF) const { - return Address(getPointer(CGF), ElementType, getAlignment(), - isKnownNonNull()); - } - void setAddress(Address address) { + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { assert(isSimple()); - V = address.getPointer(); - ElementType = address.getElementType(); - Alignment = address.getAlignment().getQuantity(); - IsKnownNonNull = address.isKnownNonNull(); + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } + Address getAddress(CodeGenFunction &CGF) const { + // FIXME: remove parameter. + return Addr; + } + + void setAddress(Address address) { Addr = address; } + // vector elt lvalue Address getVectorAddress() const { - return Address(getVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isVectorElt()); + return Addr; + } + llvm::Value *getRawVectorPointer(CodeGenFunction &CGF) const { + assert(isVectorElt()); + return Addr.emitRawPointer(CGF); } llvm::Value *getVectorPointer() const { assert(isVectorElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getVectorIdx() const { assert(isVectorElt()); @@ -374,12 +393,12 @@ public: } Address getMatrixAddress() const { - return Address(getMatrixPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isMatrixElt()); + return Addr; } llvm::Value *getMatrixPointer() const { assert(isMatrixElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getMatrixIdx() const { assert(isMatrixElt()); @@ -388,12 +407,12 @@ public: // extended vector elements. Address getExtVectorAddress() const { - return Address(getExtVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isExtVectorElt()); + return Addr; } - llvm::Value *getExtVectorPointer() const { + llvm::Value *getRawExtVectorPointer(CodeGenFunction &CGF) const { assert(isExtVectorElt()); - return V; + return Addr.emitRawPointer(CGF); } llvm::Constant *getExtVectorElts() const { assert(isExtVectorElt()); @@ -402,10 +421,14 @@ public: // bitfield lvalue Address getBitFieldAddress() const { - return Address(getBitFieldPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isBitField()); + return Addr; + } + llvm::Value *getRawBitFieldPointer(CodeGenFunction &CGF) const { + assert(isBitField()); + return Addr.emitRawPointer(CGF); } - llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; } + const CGBitFieldInfo &getBitFieldInfo() const { assert(isBitField()); return *BitFieldInfo; @@ -414,18 +437,13 @@ public: // global register lvalue llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } - static LValue MakeAddr(Address address, QualType type, ASTContext &Context, + static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - Qualifiers qs = type.getQualifiers(); - qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); - LValue R; R.LVType = Simple; - assert(address.getPointer()->getType()->isPointerTy()); - R.V = address.getPointer(); - R.ElementType = address.getElementType(); - R.IsKnownNonNull = address.isKnownNonNull(); - R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); + R.initializeSimpleLValue(Addr, type, BaseInfo, TBAAInfo, Context); + R.Addr = Addr; + assert(Addr.getType()->isPointerTy()); return R; } @@ -434,26 +452,18 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = VectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), vecAddress, BaseInfo, TBAAInfo); return R; } - static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, + static LValue MakeExtVectorElt(Address Addr, llvm::Constant *Elts, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = ExtVectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorElts = Elts; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -468,12 +478,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = BitField; - R.V = Addr.getPointer(); - R.ElementType = Addr.getElementType(); R.BitFieldInfo = &Info; - R.IsKnownNonNull = Addr.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, - TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -481,11 +487,9 @@ public: QualType type) { LValue R; R.LVType = GlobalReg; - R.V = V; - R.ElementType = nullptr; - R.IsKnownNonNull = true; - R.Initialize(type, type.getQualifiers(), alignment, + R.Initialize(type, type.getQualifiers(), Address::invalid(), LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); + R.V = V; return R; } @@ -494,12 +498,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = MatrixElt; - R.V = matAddress.getPointer(); - R.ElementType = matAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = matAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), matAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), matAddress, BaseInfo, TBAAInfo); return R; } @@ -643,17 +643,17 @@ public: return NeedsGCBarriers_t(ObjCGCFlag); } - llvm::Value *getPointer() const { - return Addr.getPointer(); + llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; + + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } Address getAddress() const { return Addr; } - bool isIgnored() const { - return !Addr.isValid(); - } + bool isIgnored() const { return !Addr.isValid(); } CharUnits getAlignment() const { return Addr.getAlignment(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index f2ebaf767452..44103884940f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -193,26 +193,35 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() { CGF.Builder.setDefaultConstrainedRounding(OldRounding); } -LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { +static LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, + bool ForPointeeType, + CodeGenFunction &CGF) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - CharUnits Alignment = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo); - Address Addr(V, ConvertTypeForMem(T), Alignment); - return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo); + CharUnits Alignment = + CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType); + Address Addr = Address(V, CGF.ConvertTypeForMem(T), Alignment); + return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); +} + +LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); } -/// Given a value of type T* that may not be to a complete object, -/// construct an l-value with the natural pointee alignment of T. LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - CharUnits Align = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, - /* forPointeeType= */ true); - Address Addr(V, ConvertTypeForMem(T), Align); - return MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); +} + +LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); } +LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); +} llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { return CGM.getTypes().ConvertTypeForMem(T); @@ -525,7 +534,8 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { ReturnBlock.getBlock()->eraseFromParent(); } if (ReturnValue.isValid()) { - auto *RetAlloca = dyn_cast(ReturnValue.getPointer()); + auto *RetAlloca = + dyn_cast(ReturnValue.emitRawPointer(*this)); if (RetAlloca && RetAlloca->use_empty()) { RetAlloca->eraseFromParent(); ReturnValue = Address::invalid(); @@ -1122,13 +1132,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, auto AI = CurFn->arg_begin(); if (CurFnInfo->getReturnInfo().isSRetAfterThis()) ++AI; - ReturnValue = - Address(&*AI, ConvertType(RetTy), - CurFnInfo->getReturnInfo().getIndirectAlign(), KnownNonNull); + ReturnValue = makeNaturalAddressForPointer( + &*AI, RetTy, CurFnInfo->getReturnInfo().getIndirectAlign(), false, + nullptr, nullptr, KnownNonNull); if (!CurFnInfo->getReturnInfo().getIndirectByVal()) { - ReturnValuePointer = CreateDefaultAlignTempAlloca( - ReturnValue.getPointer()->getType(), "result.ptr"); - Builder.CreateStore(ReturnValue.getPointer(), ReturnValuePointer); + ReturnValuePointer = + CreateDefaultAlignTempAlloca(ReturnValue.getType(), "result.ptr"); + Builder.CreateStore(ReturnValue.emitRawPointer(*this), + ReturnValuePointer); } } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { @@ -1189,8 +1200,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // or contains the address of the enclosing object). LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - // If the enclosing object was captured by value, just use its address. - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + // If the enclosing object was captured by value, just use its + // address. Sign this pointer. + CXXThisValue = ThisFieldLValue.getPointer(*this); } else { // Load the lvalue pointed to by the field, since '*this' was captured // by reference. @@ -2012,8 +2024,9 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); Address begin = dest.withElementType(CGF.Int8Ty); - llvm::Value *end = Builder.CreateInBoundsGEP( - begin.getElementType(), begin.getPointer(), sizeInChars, "vla.end"); + llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(), + begin.emitRawPointer(CGF), + sizeInChars, "vla.end"); llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock(); llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop"); @@ -2024,7 +2037,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, CGF.EmitBlock(loopBB); llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur"); - cur->addIncoming(begin.getPointer(), originBB); + cur->addIncoming(begin.emitRawPointer(CGF), originBB); CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize); @@ -2217,10 +2230,10 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, addr = addr.withElementType(baseType); } else { // Create the actual GEP. - addr = Address(Builder.CreateInBoundsGEP( - addr.getElementType(), addr.getPointer(), gepIndices, "array.begin"), - ConvertTypeForMem(eltType), - addr.getAlignment()); + addr = Address(Builder.CreateInBoundsGEP(addr.getElementType(), + addr.emitRawPointer(*this), + gepIndices, "array.begin"), + ConvertTypeForMem(eltType), addr.getAlignment()); } baseType = eltType; @@ -2561,7 +2574,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) { Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, Address Addr) { assert(D->hasAttr() && "no annotate attribute"); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.emitRawPointer(*this); llvm::Type *VTy = V->getType(); auto *PTy = dyn_cast(VTy); unsigned AS = PTy ? PTy->getAddressSpace() : 0; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e8f8aa601ed0..8dd6da5f85f1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -151,6 +151,9 @@ struct DominatingLLVMValue { /// Answer whether the given value needs extra work to be saved. static bool needsSaving(llvm::Value *value) { + if (!value) + return false; + // If it's not an instruction, we don't need to save. if (!isa(value)) return false; @@ -177,21 +180,28 @@ template <> struct DominatingValue
{ typedef Address type; struct saved_type { - DominatingLLVMValue::saved_type SavedValue; + DominatingLLVMValue::saved_type BasePtr; llvm::Type *ElementType; CharUnits Alignment; + DominatingLLVMValue::saved_type Offset; + llvm::PointerType *EffectiveType; }; static bool needsSaving(type value) { - return DominatingLLVMValue::needsSaving(value.getPointer()); + if (DominatingLLVMValue::needsSaving(value.getBasePointer()) || + DominatingLLVMValue::needsSaving(value.getOffset())) + return true; + return false; } static saved_type save(CodeGenFunction &CGF, type value) { - return { DominatingLLVMValue::save(CGF, value.getPointer()), - value.getElementType(), value.getAlignment() }; + return {DominatingLLVMValue::save(CGF, value.getBasePointer()), + value.getElementType(), value.getAlignment(), + DominatingLLVMValue::save(CGF, value.getOffset()), value.getType()}; } static type restore(CodeGenFunction &CGF, saved_type value) { - return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), - value.ElementType, value.Alignment); + return Address(DominatingLLVMValue::restore(CGF, value.BasePtr), + value.ElementType, value.Alignment, + DominatingLLVMValue::restore(CGF, value.Offset)); } }; @@ -201,14 +211,26 @@ template <> struct DominatingValue { class saved_type { enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, AggregateAddress, ComplexAddress }; - - llvm::Value *Value; - llvm::Type *ElementType; + union { + struct { + DominatingLLVMValue::saved_type first, second; + } Vals; + DominatingValue
::saved_type AggregateAddr; + }; LLVM_PREFERRED_TYPE(Kind) unsigned K : 3; - unsigned Align : 29; - saved_type(llvm::Value *v, llvm::Type *e, Kind k, unsigned a = 0) - : Value(v), ElementType(e), K(k), Align(a) {} + unsigned IsVolatile : 1; + + saved_type(DominatingLLVMValue::saved_type Val1, unsigned K) + : Vals{Val1, DominatingLLVMValue::saved_type()}, K(K) {} + + saved_type(DominatingLLVMValue::saved_type Val1, + DominatingLLVMValue::saved_type Val2) + : Vals{Val1, Val2}, K(ComplexAddress) {} + + saved_type(DominatingValue
::saved_type AggregateAddr, + bool IsVolatile, unsigned K) + : AggregateAddr(AggregateAddr), K(K) {} public: static bool needsSaving(RValue value); @@ -659,7 +681,7 @@ public: llvm::Value *Size; public: - CallLifetimeEnd(Address addr, llvm::Value *size) + CallLifetimeEnd(RawAddress addr, llvm::Value *size) : Addr(addr.getPointer()), Size(size) {} void Emit(CodeGenFunction &CGF, Flags flags) override { @@ -684,7 +706,7 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest = Address::invalid(); + RawAddress NormalCleanupDest = RawAddress::invalid(); unsigned NextCleanupDestIndex = 1; @@ -819,10 +841,10 @@ public: template void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) { if (!isInConditionalBranch()) - return pushCleanupAfterFullExprWithActiveFlag(Kind, Address::invalid(), - A...); + return pushCleanupAfterFullExprWithActiveFlag( + Kind, RawAddress::invalid(), A...); - Address ActiveFlag = createCleanupActiveFlag(); + RawAddress ActiveFlag = createCleanupActiveFlag(); assert(!DominatingValue
::needsSaving(ActiveFlag) && "cleanup active flag should never need saving"); @@ -835,7 +857,7 @@ public: template void pushCleanupAfterFullExprWithActiveFlag(CleanupKind Kind, - Address ActiveFlag, As... A) { + RawAddress ActiveFlag, As... A) { LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind, ActiveFlag.isValid()}; @@ -850,7 +872,7 @@ public: new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer + sizeof(Header)) T(A...); if (Header.IsConditional) - new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag); + new (Buffer + sizeof(Header) + sizeof(T)) RawAddress(ActiveFlag); } /// Set up the last cleanup that was pushed as a conditional @@ -859,8 +881,8 @@ public: initFullExprCleanupWithFlag(createCleanupActiveFlag()); } - void initFullExprCleanupWithFlag(Address ActiveFlag); - Address createCleanupActiveFlag(); + void initFullExprCleanupWithFlag(RawAddress ActiveFlag); + RawAddress createCleanupActiveFlag(); /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the @@ -1048,7 +1070,7 @@ public: QualType VarTy = LocalVD->getType(); if (VarTy->isReferenceType()) { Address Temp = CGF.CreateMemTemp(VarTy); - CGF.Builder.CreateStore(TempAddr.getPointer(), Temp); + CGF.Builder.CreateStore(TempAddr.emitRawPointer(CGF), Temp); TempAddr = Temp; } SavedTempAddresses.try_emplace(LocalVD, TempAddr); @@ -1243,10 +1265,12 @@ public: /// one branch or the other of a conditional expression. bool isInConditionalBranch() const { return OutermostConditional != nullptr; } - void setBeforeOutermostConditional(llvm::Value *value, Address addr) { + void setBeforeOutermostConditional(llvm::Value *value, Address addr, + CodeGenFunction &CGF) { assert(isInConditionalBranch()); llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back()); + auto store = + new llvm::StoreInst(value, addr.emitRawPointer(CGF), &block->back()); store->setAlignment(addr.getAlignment().getAsAlign()); } @@ -1601,7 +1625,7 @@ public: /// If \p StepV is null, the default increment is 1. void maybeUpdateMCDCTestVectorBitmap(const Expr *E) { if (isMCDCCoverageEnabled() && isBinaryLogicalOp(E)) { - PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr); + PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr, *this); PGO.setCurrentStmt(E); } } @@ -1609,7 +1633,7 @@ public: /// Update the MCDC temp value with the condition's evaluated result. void maybeUpdateMCDCCondBitmap(const Expr *E, llvm::Value *Val) { if (isMCDCCoverageEnabled()) { - PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val); + PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val, *this); PGO.setCurrentStmt(E); } } @@ -1704,7 +1728,7 @@ public: : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue), OldCXXThisAlignment(CGF.CXXThisAlignment), SourceLocScope(E, CGF.CurSourceLocExprScope) { - CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer(); + CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getBasePointer(); CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment(); } ~CXXDefaultInitExprScope() { @@ -2090,7 +2114,7 @@ public: llvm::Value *getExceptionFromSlot(); llvm::Value *getSelectorFromSlot(); - Address getNormalCleanupDestSlot(); + RawAddress getNormalCleanupDestSlot(); llvm::BasicBlock *getUnreachableBlock() { if (!UnreachableBlock) { @@ -2579,10 +2603,40 @@ public: // Helpers //===--------------------------------------------------------------------===// + Address mergeAddressesInConditionalExpr(Address LHS, Address RHS, + llvm::BasicBlock *LHSBlock, + llvm::BasicBlock *RHSBlock, + llvm::BasicBlock *MergeBlock, + QualType MergedType) { + Builder.SetInsertPoint(MergeBlock); + llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); + PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); + PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); + LHS.replaceBasePointer(PtrPhi); + LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); + return LHS; + } + + /// Construct an address with the natural alignment of T. If a pointer to T + /// is expected to be signed, the pointer passed to this function must have + /// been signed, and the returned Address will have the pointer authentication + /// information needed to authenticate the signed pointer. + Address makeNaturalAddressForPointer( + llvm::Value *Ptr, QualType T, CharUnits Alignment = CharUnits::Zero(), + bool ForPointeeType = false, LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) { + if (Alignment.isZero()) + Alignment = + CGM.getNaturalTypeAlignment(T, BaseInfo, TBAAInfo, ForPointeeType); + return Address(Ptr, ConvertTypeForMem(T), Alignment, nullptr, + IsKnownNonNull); + } + LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source = AlignmentSource::Type) { - return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(T)); + return MakeAddrLValue(Addr, T, LValueBaseInfo(Source), + CGM.getTBAAAccessInfo(T)); } LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo, @@ -2592,6 +2646,14 @@ public: LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source = AlignmentSource::Type) { + return MakeAddrLValue(makeNaturalAddressForPointer(V, T, Alignment), T, + LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); + } + + /// Same as MakeAddrLValue above except that the pointer is known to be + /// unsigned. + LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, + AlignmentSource Source = AlignmentSource::Type) { Address Addr(V, ConvertTypeForMem(T), Alignment); return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); @@ -2604,9 +2666,18 @@ public: TBAAAccessInfo()); } + /// Given a value of type T* that may not be to a complete object, construct + /// an l-value with the natural pointee alignment of T. LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); + LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); + /// Same as MakeNaturalAlignPointeeAddrLValue except that the pointer is known + /// to be unsigned. + LValue MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T); + + LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T); + Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo = nullptr, TBAAAccessInfo *PointeeTBAAInfo = nullptr); @@ -2655,13 +2726,13 @@ public: /// more efficient if the caller knows that the address will not be exposed. llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr); - Address CreateTempAlloca(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr, - Address *Alloca = nullptr); - Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); + RawAddress CreateTempAlloca(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr, + RawAddress *Alloca = nullptr); + RawAddress CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr); /// CreateDefaultAlignedTempAlloca - This creates an alloca with the /// default ABI alignment of the given LLVM type. @@ -2673,8 +2744,8 @@ public: /// not hand this address off to arbitrary IRGen routines, and especially /// do not pass it as an argument to a function that might expect a /// properly ABI-aligned value. - Address CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name = "tmp"); + RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name = "tmp"); /// CreateIRTemp - Create a temporary IR object of the given type, with /// appropriate alignment. This routine should only be used when an temporary @@ -2684,32 +2755,31 @@ public: /// /// That is, this is exactly equivalent to CreateMemTemp, but calling /// ConvertType instead of ConvertTypeForMem. - Address CreateIRTemp(QualType T, const Twine &Name = "tmp"); + RawAddress CreateIRTemp(QualType T, const Twine &Name = "tmp"); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen and cast it to the default address space. Returns /// the original alloca instruction by \p Alloca if it is not nullptr. - Address CreateMemTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr); - Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp", - Address *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, CharUnits Align, + const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen without casting it to the default address space. - Address CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); - Address CreateMemTempWithoutCast(QualType T, CharUnits Align, - const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, CharUnits Align, + const Twine &Name = "tmp"); /// CreateAggTemp - Create a temporary memory object for the given /// aggregate type. AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr) { - return AggValueSlot::forAddr(CreateMemTemp(T, Name, Alloca), - T.getQualifiers(), - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); + RawAddress *Alloca = nullptr) { + return AggValueSlot::forAddr( + CreateMemTemp(T, Name, Alloca), T.getQualifiers(), + AggValueSlot::IsNotDestructed, AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap); } /// EvaluateExprAsBool - Perform the usual unary conversions on the specified @@ -3083,6 +3153,25 @@ public: /// calls to EmitTypeCheck can be skipped. bool sanitizePerformTypeCheck() const; + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, + QualType Type, SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, LV.emitRawPointer(*this), Type, LV.getAlignment(), + SkippedChecks, ArraySize); + } + + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, Address Addr, + QualType Type, CharUnits Alignment = CharUnits::Zero(), + SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, Addr.emitRawPointer(*this), Type, Alignment, + SkippedChecks, ArraySize); + } + /// Emit a check that \p V is the address of storage of the /// appropriate size and alignment for an object of type \p Type /// (or if ArraySize is provided, for an array of that bound). @@ -3183,17 +3272,17 @@ public: /// Address with original alloca instruction. Invalid if the variable was /// emitted as a global constant. - Address AllocaAddr; + RawAddress AllocaAddr; struct Invalid {}; AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()), - AllocaAddr(Address::invalid()) {} + AllocaAddr(RawAddress::invalid()) {} AutoVarEmission(const VarDecl &variable) : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr), IsEscapingByRef(false), IsConstantAggregate(false), - SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {} + SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {} bool wasEmittedAsGlobal() const { return !Addr.isValid(); } @@ -3216,7 +3305,7 @@ public: } /// Returns the address for the original alloca instruction. - Address getOriginalAllocatedAddress() const { return AllocaAddr; } + RawAddress getOriginalAllocatedAddress() const { return AllocaAddr; } /// Returns the address of the object within this declaration. /// Note that this does not chase the forwarding pointer for @@ -3246,23 +3335,32 @@ public: llvm::GlobalValue::LinkageTypes Linkage); class ParamValue { - llvm::Value *Value; - llvm::Type *ElementType; - unsigned Alignment; - ParamValue(llvm::Value *V, llvm::Type *T, unsigned A) - : Value(V), ElementType(T), Alignment(A) {} + union { + Address Addr; + llvm::Value *Value; + }; + + bool IsIndirect; + + ParamValue(llvm::Value *V) : Value(V), IsIndirect(false) {} + ParamValue(Address A) : Addr(A), IsIndirect(true) {} + public: static ParamValue forDirect(llvm::Value *value) { - return ParamValue(value, nullptr, 0); + return ParamValue(value); } static ParamValue forIndirect(Address addr) { assert(!addr.getAlignment().isZero()); - return ParamValue(addr.getPointer(), addr.getElementType(), - addr.getAlignment().getQuantity()); + return ParamValue(addr); } - bool isIndirect() const { return Alignment != 0; } - llvm::Value *getAnyValue() const { return Value; } + bool isIndirect() const { return IsIndirect; } + llvm::Value *getAnyValue() const { + if (!isIndirect()) + return Value; + assert(!Addr.hasOffset() && "unexpected offset"); + return Addr.getBasePointer(); + } llvm::Value *getDirectValue() const { assert(!isIndirect()); @@ -3271,8 +3369,7 @@ public: Address getIndirectAddress() const { assert(isIndirect()); - return Address(Value, ElementType, CharUnits::fromQuantity(Alignment), - KnownNonNull); + return Addr; } }; @@ -4182,6 +4279,9 @@ public: const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name = ""); + llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef
args, + const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, const Twine &name = ""); @@ -4208,6 +4308,12 @@ public: CXXDtorType Type, const CXXRecordDecl *RD); + llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { + return Addr.getBasePointer(); + } + + bool isPointerKnownNonNull(const Expr *E); + // Return the copy constructor name with the prefix "__copy_constructor_" // removed. static std::string getNonTrivialCopyConstructorStr(QualType QT, @@ -4780,6 +4886,11 @@ public: SourceLocation Loc, const Twine &Name = ""); + Address EmitCheckedInBoundsGEP(Address Addr, ArrayRef IdxList, + llvm::Type *elementType, bool SignedIndices, + bool IsSubtraction, SourceLocation Loc, + CharUnits Align, const Twine &Name = ""); + /// Specifies which type of sanitizer check to apply when handling a /// particular builtin. enum BuiltinCheckKind { @@ -4842,6 +4953,10 @@ public: void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, AbstractCallee AC, unsigned ParmNum); + void EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, AbstractCallee AC, + unsigned ParmNum); + /// EmitCallArg - Emit a single call argument. void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); @@ -5050,7 +5165,7 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); CGF.Builder.CreateStore(value, alloca); - return saved_type(alloca.getPointer(), true); + return saved_type(alloca.emitRawPointer(CGF), true); } inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e3ed5e90f2d3..00b3bfcaa0bc 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -7267,7 +7267,7 @@ void CodeGenFunction::EmitDeclMetadata() { for (auto &I : LocalDeclMap) { const Decl *D = I.first; - llvm::Value *Addr = I.second.getPointer(); + llvm::Value *Addr = I.second.emitRawPointer(*this); if (auto *Alloca = dyn_cast(Addr)) { llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); Alloca->setMetadata( diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 2619edfeb7dc..76704c4d7be4 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1239,7 +1239,8 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) { void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr) { + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1262,7 +1263,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, Builder.getInt64(FunctionHash), Builder.getInt32(RegionMCDCState->BitmapBytes), Builder.getInt32(MCDCTestVectorBitmapOffset), - MCDCCondBitmapAddr.getPointer()}; + MCDCCondBitmapAddr.emitRawPointer(CGF)}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args); } @@ -1283,7 +1284,8 @@ void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr, - llvm::Value *Val) { + llvm::Value *Val, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1312,7 +1314,7 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), Builder.getInt64(FunctionHash), Builder.getInt32(Branch.ID), - MCDCCondBitmapAddr.getPointer(), Val}; + MCDCCondBitmapAddr.emitRawPointer(CGF), Val}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update), Args); diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 036fbf6815a4..9d66ffad6f43 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -113,12 +113,14 @@ public: void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, llvm::Value *StepV); void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr); + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF); void emitMCDCParameters(CGBuilderTy &Builder); void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr); void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, llvm::Value *Val); + Address MCDCCondBitmapAddr, llvm::Value *Val, + CodeGenFunction &CGF); /// Return the region count for the counter at the given index. uint64_t getRegionCount(const Stmt *S) { diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index bdd53a192f82..fd71317572f0 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -307,10 +307,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase); - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -646,7 +642,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( // Apply the adjustment and cast back to the original struct type // for consistency. - llvm::Value *This = ThisAddr.getPointer(); + llvm::Value *This = ThisAddr.emitRawPointer(CGF); This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj); ThisPtrForCall = This; @@ -850,7 +846,7 @@ llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( CGBuilderTy &Builder = CGF.Builder; // Apply the offset, which we assume is non-null. - return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.getPointer(), MemPtr, + return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr, "memptr.offset"); } @@ -1245,7 +1241,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, CGF.getPointerAlign()); // Apply the offset. - llvm::Value *CompletePtr = Ptr.getPointer(); + llvm::Value *CompletePtr = Ptr.emitRawPointer(CGF); CompletePtr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset); @@ -1482,7 +1478,8 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastCall( computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity()); // Emit the call to __dynamic_cast. - llvm::Value *Args[] = {ThisAddr.getPointer(), SrcRTTI, DestRTTI, OffsetHint}; + llvm::Value *Args[] = {ThisAddr.emitRawPointer(CGF), SrcRTTI, DestRTTI, + OffsetHint}; llvm::Value *Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), Args); @@ -1571,7 +1568,7 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast( VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy)); llvm::Value *Success = CGF.Builder.CreateICmpEQ( VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl)); - llvm::Value *Result = ThisAddr.getPointer(); + llvm::Value *Result = ThisAddr.emitRawPointer(CGF); if (!Offset->isZero()) Result = CGF.Builder.CreateInBoundsGEP( CGF.CharTy, Result, @@ -1611,7 +1608,7 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top"); } // Finally, add the offset to the pointer. - return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.getPointer(), + return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.emitRawPointer(CGF), OffsetToTop); } @@ -1792,8 +1789,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, - nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, VTT, VTTTy, nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1952,11 +1949,6 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( CGF.getPointerAlign()); } -llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - return getVTableAddressPoint(Base, VTableClass); -} - llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); @@ -2088,8 +2080,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( ThisTy = D->getDestroyedType(); } - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, - QualType(), nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + nullptr, QualType(), nullptr); return nullptr; } @@ -2162,7 +2154,7 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, int64_t VirtualAdjustment, bool IsReturnAdjustment) { if (!NonVirtualAdjustment && !VirtualAdjustment) - return InitialPtr.getPointer(); + return InitialPtr.emitRawPointer(CGF); Address V = InitialPtr.withElementType(CGF.Int8Ty); @@ -2195,10 +2187,10 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, CGF.getPointerAlign()); } // Adjust our pointer. - ResultPtr = CGF.Builder.CreateInBoundsGEP( - V.getElementType(), V.getPointer(), Offset); + ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getElementType(), + V.emitRawPointer(CGF), Offset); } else { - ResultPtr = V.getPointer(); + ResultPtr = V.emitRawPointer(CGF); } // In a derived-to-base conversion, the non-virtual adjustment is @@ -2284,7 +2276,7 @@ Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie"); - CGF.Builder.CreateCall(F, NumElementsPtr.getPointer()); + CGF.Builder.CreateCall(F, NumElementsPtr.emitRawPointer(CGF)); } // Finally, compute a pointer to the actual data buffer by skipping @@ -2315,7 +2307,7 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, llvm::FunctionType::get(CGF.SizeTy, CGF.UnqualPtrTy, false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie"); - return CGF.Builder.CreateCall(F, numElementsPtr.getPointer()); + return CGF.Builder.CreateCall(F, numElementsPtr.emitRawPointer(CGF)); } CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { @@ -2627,7 +2619,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // Call __cxa_guard_release. This cannot throw. CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), - guardAddr.getPointer()); + guardAddr.emitRawPointer(CGF)); } else if (D.isLocalVarDecl()) { // For local variables, store 1 into the first byte of the guard variable // after the object initialization completes so that initialization is @@ -3120,10 +3112,10 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, LValue LV; if (VD->getType()->isReferenceType()) - LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType); + LV = CGF.MakeNaturalAlignRawAddrLValue(CallVal, LValType); else - LV = CGF.MakeAddrLValue(CallVal, LValType, - CGF.getContext().getDeclAlign(VD)); + LV = CGF.MakeRawAddrLValue(CallVal, LValType, + CGF.getContext().getDeclAlign(VD)); // FIXME: need setObjCGCLValueClass? return LV; } @@ -4604,7 +4596,7 @@ static void InitCatchParam(CodeGenFunction &CGF, CGF.Builder.CreateStore(Casted, ExnPtrTmp); // Bind the reference to the temporary. - AdjustedExn = ExnPtrTmp.getPointer(); + AdjustedExn = ExnPtrTmp.emitRawPointer(CGF); } } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 172c4c937b97..d38a26940a3c 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -327,10 +327,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -937,7 +933,7 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, } CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); - CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); + CPI->setArgOperand(2, var.getObjectAddress(CGF).emitRawPointer(CGF)); CGF.EHStack.pushCleanup(NormalCleanup, CPI); CGF.EmitAutoVarCleanups(var); } @@ -974,7 +970,7 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, llvm::Value *Offset = GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP( - Value.getElementType(), Value.getPointer(), Offset); + Value.getElementType(), Value.emitRawPointer(CGF), Offset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); return std::make_tuple(Address(Ptr, CGF.Int8Ty, VBaseAlign), Offset, @@ -1011,7 +1007,7 @@ llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, llvm::Type *StdTypeInfoPtrTy) { std::tie(ThisPtr, std::ignore, std::ignore) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); - llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()); + llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.emitRawPointer(CGF)); return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); } @@ -1033,7 +1029,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastCall( llvm::Value *Offset; std::tie(This, Offset, std::ignore) = performBaseAdjustment(CGF, This, SrcRecordTy); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = This.emitRawPointer(CGF); Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); // PVOID __RTDynamicCast( @@ -1065,7 +1061,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, llvm::FunctionCallee Function = CGF.CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), "__RTCastToVoid"); - llvm::Value *Args[] = {Value.getPointer()}; + llvm::Value *Args[] = {Value.emitRawPointer(CGF)}; return CGF.EmitRuntimeCall(Function, Args); } @@ -1493,7 +1489,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( llvm::Value *VBaseOffset = GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); llvm::Value *VBasePtr = CGF.Builder.CreateInBoundsGEP( - Result.getElementType(), Result.getPointer(), VBaseOffset); + Result.getElementType(), Result.emitRawPointer(CGF), VBaseOffset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); Result = Address(VBasePtr, CGF.Int8Ty, VBaseAlign); @@ -1660,7 +1656,8 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, llvm::Value *Implicit = getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating); // = nullptr - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, /*ImplicitParam=*/Implicit, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1791,13 +1788,6 @@ MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, return VFTablesMap[ID]; } -llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); - assert(VFTable && "Couldn't find a vftable for the given base?"); - return VFTable; -} - llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { // getAddrOfVTable may return 0 if asked to get an address of a vtable which @@ -2013,8 +2003,9 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( } This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, - ImplicitParam, Context.IntTy, CE); + RValue RV = + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } @@ -2212,13 +2203,13 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This, const ThisAdjustment &TA) { if (TA.isEmpty()) - return This.getPointer(); + return This.emitRawPointer(CGF); This = This.withElementType(CGF.Int8Ty); llvm::Value *V; if (TA.Virtual.isEmpty()) { - V = This.getPointer(); + V = This.emitRawPointer(CGF); } else { assert(TA.Virtual.Microsoft.VtordispOffset < 0); // Adjust the this argument based on the vtordisp value. @@ -2227,7 +2218,7 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); VtorDispPtr = VtorDispPtr.withElementType(CGF.Int32Ty); llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); - V = CGF.Builder.CreateGEP(This.getElementType(), This.getPointer(), + V = CGF.Builder.CreateGEP(This.getElementType(), This.emitRawPointer(CGF), CGF.Builder.CreateNeg(VtorDisp)); // Unfortunately, having applied the vtordisp means that we no @@ -2264,11 +2255,11 @@ llvm::Value * MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const ReturnAdjustment &RA) { if (RA.isEmpty()) - return Ret.getPointer(); + return Ret.emitRawPointer(CGF); Ret = Ret.withElementType(CGF.Int8Ty); - llvm::Value *V = Ret.getPointer(); + llvm::Value *V = Ret.emitRawPointer(CGF); if (RA.Virtual.Microsoft.VBIndex) { assert(RA.Virtual.Microsoft.VBIndex > 0); int32_t IntSize = CGF.getIntSize().getQuantity(); @@ -2583,7 +2574,7 @@ struct ResetGuardBit final : EHScopeStack::Cleanup { struct CallInitThreadAbort final : EHScopeStack::Cleanup { llvm::Value *Guard; - CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} + CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {} void Emit(CodeGenFunction &CGF, Flags flags) override { // Calling _Init_thread_abort will reset the guard's state. @@ -3123,8 +3114,8 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, llvm::Value **VBPtrOut) { CGBuilderTy &Builder = CGF.Builder; // Load the vbtable pointer from the vbptr in the instance. - llvm::Value *VBPtr = Builder.CreateInBoundsGEP(CGM.Int8Ty, This.getPointer(), - VBPtrOffset, "vbptr"); + llvm::Value *VBPtr = Builder.CreateInBoundsGEP( + CGM.Int8Ty, This.emitRawPointer(CGF), VBPtrOffset, "vbptr"); if (VBPtrOut) *VBPtrOut = VBPtr; @@ -3203,7 +3194,7 @@ llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( Builder.CreateBr(SkipAdjustBB); CGF.EmitBlock(SkipAdjustBB); llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); - Phi->addIncoming(Base.getPointer(), OriginalBB); + Phi->addIncoming(Base.emitRawPointer(CGF), OriginalBB); Phi->addIncoming(AdjustedBase, VBaseAdjustBB); return Phi; } @@ -3238,7 +3229,7 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - Addr = Base.getPointer(); + Addr = Base.emitRawPointer(CGF); } // Apply the offset, which we assume is non-null. @@ -3526,7 +3517,7 @@ CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - ThisPtrForCall = This.getPointer(); + ThisPtrForCall = This.emitRawPointer(CGF); } if (NonVirtualBaseAdjustment) @@ -4445,10 +4436,7 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { llvm::GlobalVariable *TI = getThrowInfo(ThrowType); // Call into the runtime to throw the exception. - llvm::Value *Args[] = { - AI.getPointer(), - TI - }; + llvm::Value *Args[] = {AI.emitRawPointer(CGF), TI}; CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); } diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 6893b50a3cfe..b1dfe5bf8f27 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -295,6 +295,11 @@ public: /// Get the AST address space for alloca. virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; } + Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, + LangAS SrcAddr, LangAS DestAddr, + llvm::Type *DestTy, + bool IsNonNull = false) const; + /// Perform address space cast of an expression of pointer type. /// \param V is the LLVM value to be casted to another address space. /// \param SrcAddr is the language address space of \p V. diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index 8718f1ecf3a7..7dce5042c3dc 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -85,7 +85,7 @@ private: LValue Src) { llvm::Value *Handle = nullptr; llvm::Constant *C = - llvm::dyn_cast(Src.getAddress(CGF).getPointer()); + llvm::dyn_cast(Src.getAddress(CGF).emitRawPointer(CGF)); // Lookup `addrspacecast` through the constant pointer if any. if (auto *ASC = llvm::dyn_cast_or_null(C)) C = llvm::cast(ASC->getPointerOperand()); diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 00b04723f17d..362add30b435 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -513,9 +513,10 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8); llvm::Value *RegOffset = Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity())); - RegAddr = Address( - Builder.CreateInBoundsGEP(CGF.Int8Ty, RegAddr.getPointer(), RegOffset), - DirectTy, RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); + RegAddr = Address(Builder.CreateInBoundsGEP( + CGF.Int8Ty, RegAddr.emitRawPointer(CGF), RegOffset), + DirectTy, + RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); // Increase the used-register count. NumRegs = @@ -551,7 +552,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Round up address of argument to alignment CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); if (Align > OverflowAreaAlign) { - llvm::Value *Ptr = OverflowArea.getPointer(); + llvm::Value *Ptr = OverflowArea.emitRawPointer(CGF); OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align), OverflowArea.getElementType(), Align); } @@ -560,7 +561,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Increase the overflow area. OverflowArea = Builder.CreateConstInBoundsByteGEP(OverflowArea, Size); - Builder.CreateStore(OverflowArea.getPointer(), OverflowAreaAddr); + Builder.CreateStore(OverflowArea.emitRawPointer(CGF), OverflowAreaAddr); CGF.EmitBranch(Cont); } diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index a337a52a94ec..9025a633f328 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -326,7 +326,7 @@ Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update VAList. Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); - Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); return ArgAddr.withElementType(ArgTy); } diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index 6eb0c6ef2f7d..deaafc85a315 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -306,7 +306,7 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update overflow_arg_area_ptr pointer llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( - OverflowArgArea.getElementType(), OverflowArgArea.getPointer(), + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); @@ -382,10 +382,9 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, Address MemAddr = RawMemAddr.withElementType(DirectTy); // Update overflow_arg_area_ptr pointer - llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), - OverflowArgArea.getPointer(), PaddedSizeV, - "overflow_arg_area"); + llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), + PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); CGF.EmitBranch(ContBlock); diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index aeb48f851e16..88edb781a947 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -180,7 +180,7 @@ Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Increment the VAList. if (!ArgSize.isZero()) { Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize); - Builder.CreateStore(APN.getPointer(), VAListAddr); + Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr); } return Val; diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 3a90eee5f1c9..aa20c758d84a 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -575,7 +575,7 @@ public: // Emit code to generate this result as a Value *. std::string asValue() override { if (AddressType) - return "(" + varname() + ".getPointer())"; + return "(" + varname() + ".emitRawPointer(*this))"; return Result::asValue(); } bool hasIntegerValue() const override { return Immediate; } diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 2a0c1e9e8c44..2e2ec9a1c830 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -2708,6 +2708,7 @@ public: IRBuilder(const IRBuilder &) = delete; InserterTy &getInserter() { return Inserter; } + const InserterTy &getInserter() const { return Inserter; } }; template -- GitLab From cd17082b24079a31eff0057abe407da5cfb7b0fc Mon Sep 17 00:00:00 2001 From: OverMighty Date: Wed, 27 Mar 2024 19:28:27 +0000 Subject: [PATCH 109/541] [libc][math][c23] Add remaining linux/* entrypoints for {,u}fromfp{,x}* (#86692) --- libc/config/linux/aarch64/entrypoints.txt | 16 ++++++++++++ libc/config/linux/arm/entrypoints.txt | 12 +++++++++ libc/config/linux/riscv/entrypoints.txt | 16 ++++++++++++ libc/docs/math/index.rst | 32 +++++++++++------------ 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 78da7f0b334b..ab0be7e35dce 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -396,6 +396,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl + libc.src.math.fromfp + libc.src.math.fromfpf + libc.src.math.fromfpl + libc.src.math.fromfpx + libc.src.math.fromfpxf + libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -478,6 +484,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl + libc.src.math.ufromfp + libc.src.math.ufromfpf + libc.src.math.ufromfpl + libc.src.math.ufromfpx + libc.src.math.ufromfpxf + libc.src.math.ufromfpxl ) if(LIBC_TYPES_HAS_FLOAT128) @@ -500,6 +512,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 + libc.src.math.fromfpf128 + libc.src.math.fromfpxf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 @@ -517,6 +531,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 + libc.src.math.ufromfpf128 + libc.src.math.ufromfpxf128 ) endif() diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 6e63e270280e..1d9d5ed67200 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -263,6 +263,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl + libc.src.math.fromfp + libc.src.math.fromfpf + libc.src.math.fromfpl + libc.src.math.fromfpx + libc.src.math.fromfpxf + libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -345,6 +351,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl + libc.src.math.ufromfp + libc.src.math.ufromfpf + libc.src.math.ufromfpl + libc.src.math.ufromfpx + libc.src.math.ufromfpxf + libc.src.math.ufromfpxl ) set(TARGET_LLVMLIBC_ENTRYPOINTS diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 5aae4e246cfb..96acd999efda 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -404,6 +404,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl + libc.src.math.fromfp + libc.src.math.fromfpf + libc.src.math.fromfpl + libc.src.math.fromfpx + libc.src.math.fromfpxf + libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -486,6 +492,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl + libc.src.math.ufromfp + libc.src.math.ufromfpf + libc.src.math.ufromfpl + libc.src.math.ufromfpx + libc.src.math.ufromfpxf + libc.src.math.ufromfpxl ) if(LIBC_TYPES_HAS_FLOAT128) @@ -508,6 +520,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 + libc.src.math.fromfpf128 + libc.src.math.fromfpxf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 @@ -525,6 +539,8 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 + libc.src.math.ufromfpf128 + libc.src.math.ufromfpxf128 ) endif() diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 080b6a4427f5..d8dee3c90619 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -190,21 +190,21 @@ Basic Operations +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | frexpf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfp | |check| | | | | | | | | | | | | +| fromfp | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpf | |check| | | | | | | | | | | | | +| fromfpf | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpl | |check| | | | | | | | | | | | | +| fromfpl | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpf128 | |check| | | | | | | | | | | | | +| fromfpf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpx | |check| | | | | | | | | | | | | +| fromfpx | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpxf | |check| | | | | | | | | | | | | +| fromfpxf | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpxl | |check| | | | | | | | | | | | | +| fromfpxl | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpxf128 | |check| | | | | | | | | | | | | +| fromfpxf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | ilogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ @@ -364,21 +364,21 @@ Basic Operations +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | truncf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfp | |check| | | | | | | | | | | | | +| ufromfp | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpf | |check| | | | | | | | | | | | | +| ufromfpf | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpl | |check| | | | | | | | | | | | | +| ufromfpl | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpf128 | |check| | | | | | | | | | | | | +| ufromfpf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpx | |check| | | | | | | | | | | | | +| ufromfpx | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpxf | |check| | | | | | | | | | | | | +| ufromfpxf | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpxl | |check| | | | | | | | | | | | | +| ufromfpxl | |check| | |check| | |check| | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpxf128 | |check| | | | | | | | | | | | | +| ufromfpxf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -- GitLab From 4a5056be2e38bdf27125a41f3f1b7ae4233f9713 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 27 Mar 2024 14:37:55 -0500 Subject: [PATCH 110/541] [Libomptarget][NFC] Remove trivially true checks on function pointers (#86804) Summary: Previously we had an interface that checked these functions pointers to see if they are implemented by the plugin. This was removed as currently every single function is implemented as a part of the common interface. These checks are now always true and do nothing. --- openmp/libomptarget/src/device.cpp | 61 ++++++--------------------- openmp/libomptarget/src/interface.cpp | 6 +-- openmp/libomptarget/src/omptarget.cpp | 14 +++--- 3 files changed, 19 insertions(+), 62 deletions(-) diff --git a/openmp/libomptarget/src/device.cpp b/openmp/libomptarget/src/device.cpp index 3345277d91d3..44a2facc8d3d 100644 --- a/openmp/libomptarget/src/device.cpp +++ b/openmp/libomptarget/src/device.cpp @@ -79,8 +79,7 @@ DeviceTy::~DeviceTy() { llvm::Error DeviceTy::init() { // Make call to init_requires if it exists for this plugin. int32_t Ret = 0; - if (RTL->init_requires) - Ret = RTL->init_requires(PM->getRequirements()); + Ret = RTL->init_requires(PM->getRequirements()); if (Ret != OFFLOAD_SUCCESS) return llvm::createStringError( llvm::inconvertibleErrorCode(), @@ -154,8 +153,6 @@ int32_t DeviceTy::submitData(void *TgtPtrBegin, void *HstPtrBegin, int64_t Size, omp_get_initial_device(), HstPtrBegin, DeviceID, TgtPtrBegin, Size, /*CodePtr=*/OMPT_GET_RETURN_ADDRESS);) - if (!AsyncInfo || !RTL->data_submit_async || !RTL->synchronize) - return RTL->data_submit(RTLDeviceID, TgtPtrBegin, HstPtrBegin, Size); return RTL->data_submit_async(RTLDeviceID, TgtPtrBegin, HstPtrBegin, Size, AsyncInfo); } @@ -176,8 +173,6 @@ int32_t DeviceTy::retrieveData(void *HstPtrBegin, void *TgtPtrBegin, DeviceID, TgtPtrBegin, omp_get_initial_device(), HstPtrBegin, Size, /*CodePtr=*/OMPT_GET_RETURN_ADDRESS);) - if (!RTL->data_retrieve_async || !RTL->synchronize) - return RTL->data_retrieve(RTLDeviceID, HstPtrBegin, TgtPtrBegin, Size); return RTL->data_retrieve_async(RTLDeviceID, HstPtrBegin, TgtPtrBegin, Size, AsyncInfo); } @@ -196,7 +191,7 @@ int32_t DeviceTy::dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr, RegionInterface.getCallbacks(), RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr, Size, /*CodePtr=*/OMPT_GET_RETURN_ADDRESS);) - if (!AsyncInfo || !RTL->data_exchange_async || !RTL->synchronize) { + if (!AsyncInfo) { assert(RTL->data_exchange && "RTL->data_exchange is nullptr"); return RTL->data_exchange(RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr, Size); @@ -206,9 +201,6 @@ int32_t DeviceTy::dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr, } int32_t DeviceTy::notifyDataMapped(void *HstPtr, int64_t Size) { - if (!RTL->data_notify_mapped) - return OFFLOAD_SUCCESS; - DP("Notifying about new mapping: HstPtr=" DPxMOD ", Size=%" PRId64 "\n", DPxPTR(HstPtr), Size); @@ -220,9 +212,6 @@ int32_t DeviceTy::notifyDataMapped(void *HstPtr, int64_t Size) { } int32_t DeviceTy::notifyDataUnmapped(void *HstPtr) { - if (!RTL->data_notify_unmapped) - return OFFLOAD_SUCCESS; - DP("Notifying about an unmapping: HstPtr=" DPxMOD "\n", DPxPTR(HstPtr)); if (RTL->data_notify_unmapped(RTLDeviceID, HstPtr)) { @@ -242,70 +231,46 @@ int32_t DeviceTy::launchKernel(void *TgtEntryPtr, void **TgtVarsPtr, // Run region on device bool DeviceTy::printDeviceInfo() { - if (!RTL->print_device_info) - return false; RTL->print_device_info(RTLDeviceID); return true; } // Whether data can be copied to DstDevice directly bool DeviceTy::isDataExchangable(const DeviceTy &DstDevice) { - if (RTL != DstDevice.RTL || !RTL->is_data_exchangable) + if (RTL != DstDevice.RTL) return false; if (RTL->is_data_exchangable(RTLDeviceID, DstDevice.RTLDeviceID)) - return (RTL->data_exchange != nullptr) || - (RTL->data_exchange_async != nullptr); - + return true; return false; } int32_t DeviceTy::synchronize(AsyncInfoTy &AsyncInfo) { - if (RTL->synchronize) - return RTL->synchronize(RTLDeviceID, AsyncInfo); - return OFFLOAD_SUCCESS; + return RTL->synchronize(RTLDeviceID, AsyncInfo); } int32_t DeviceTy::queryAsync(AsyncInfoTy &AsyncInfo) { - if (RTL->query_async) - return RTL->query_async(RTLDeviceID, AsyncInfo); - - return synchronize(AsyncInfo); + return RTL->query_async(RTLDeviceID, AsyncInfo); } int32_t DeviceTy::createEvent(void **Event) { - if (RTL->create_event) - return RTL->create_event(RTLDeviceID, Event); - - return OFFLOAD_SUCCESS; + return RTL->create_event(RTLDeviceID, Event); } int32_t DeviceTy::recordEvent(void *Event, AsyncInfoTy &AsyncInfo) { - if (RTL->record_event) - return RTL->record_event(RTLDeviceID, Event, AsyncInfo); - - return OFFLOAD_SUCCESS; + return RTL->record_event(RTLDeviceID, Event, AsyncInfo); } int32_t DeviceTy::waitEvent(void *Event, AsyncInfoTy &AsyncInfo) { - if (RTL->wait_event) - return RTL->wait_event(RTLDeviceID, Event, AsyncInfo); - - return OFFLOAD_SUCCESS; + return RTL->wait_event(RTLDeviceID, Event, AsyncInfo); } int32_t DeviceTy::syncEvent(void *Event) { - if (RTL->sync_event) - return RTL->sync_event(RTLDeviceID, Event); - - return OFFLOAD_SUCCESS; + return RTL->sync_event(RTLDeviceID, Event); } int32_t DeviceTy::destroyEvent(void *Event) { - if (RTL->create_event) - return RTL->destroy_event(RTLDeviceID, Event); - - return OFFLOAD_SUCCESS; + return RTL->destroy_event(RTLDeviceID, Event); } void DeviceTy::dumpOffloadEntries() { @@ -321,7 +286,5 @@ void DeviceTy::dumpOffloadEntries() { } bool DeviceTy::useAutoZeroCopy() { - if (RTL->use_auto_zero_copy) - return RTL->use_auto_zero_copy(RTLDeviceID); - return false; + return RTL->use_auto_zero_copy(RTLDeviceID); } diff --git a/openmp/libomptarget/src/interface.cpp b/openmp/libomptarget/src/interface.cpp index b7f547f1ec3d..b562ba8818c3 100644 --- a/openmp/libomptarget/src/interface.cpp +++ b/openmp/libomptarget/src/interface.cpp @@ -456,10 +456,8 @@ EXTERN void __tgt_set_info_flag(uint32_t NewInfoLevel) { assert(PM && "Runtime not initialized"); std::atomic &InfoLevel = getInfoLevelInternal(); InfoLevel.store(NewInfoLevel); - for (auto &R : PM->pluginAdaptors()) { - if (R.set_info_flag) - R.set_info_flag(NewInfoLevel); - } + for (auto &R : PM->pluginAdaptors()) + R.set_info_flag(NewInfoLevel); } EXTERN int __tgt_print_device_info(int64_t DeviceId) { diff --git a/openmp/libomptarget/src/omptarget.cpp b/openmp/libomptarget/src/omptarget.cpp index 5bbf3a455c72..803e941fe838 100644 --- a/openmp/libomptarget/src/omptarget.cpp +++ b/openmp/libomptarget/src/omptarget.cpp @@ -481,12 +481,10 @@ void *targetLockExplicit(void *HostPtr, size_t Size, int DeviceNum, FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); int32_t Err = 0; - if (!DeviceOrErr->RTL->data_lock) { - Err = DeviceOrErr->RTL->data_lock(DeviceNum, HostPtr, Size, &RC); - if (Err) { - DP("Could not lock ptr %p\n", HostPtr); - return nullptr; - } + Err = DeviceOrErr->RTL->data_lock(DeviceNum, HostPtr, Size, &RC); + if (Err) { + DP("Could not lock ptr %p\n", HostPtr); + return nullptr; } DP("%s returns device ptr " DPxMOD "\n", Name, DPxPTR(RC)); return RC; @@ -499,9 +497,7 @@ void targetUnlockExplicit(void *HostPtr, int DeviceNum, const char *Name) { if (!DeviceOrErr) FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); - if (!DeviceOrErr->RTL->data_unlock) - DeviceOrErr->RTL->data_unlock(DeviceNum, HostPtr); - + DeviceOrErr->RTL->data_unlock(DeviceNum, HostPtr); DP("%s returns\n", Name); } -- GitLab From 685d7855acb28f89aa948e0056d2807bf30d3971 Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Wed, 27 Mar 2024 14:19:00 -0500 Subject: [PATCH 111/541] Fix the -Wmissing-designated-field-initializers on the clang-ppc64le-rhel bot --- compiler-rt/lib/scudo/standalone/tests/strings_test.cpp | 2 +- compiler-rt/lib/scudo/standalone/tests/vector_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp index 3e41f67ba922..17a596d712d0 100644 --- a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp @@ -136,7 +136,7 @@ TEST(ScudoStringsTest, CapacityIncreaseFails) { rlimit Limit = {}; EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit)); - rlimit EmptyLimit = {.rlim_max = Limit.rlim_max}; + rlimit EmptyLimit = {.rlim_cur = 0, .rlim_max = Limit.rlim_max}; EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit)); // Test requires that the default length is at least 6 characters. diff --git a/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp b/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp index b7678678d8a2..add62c5a42a3 100644 --- a/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp @@ -55,7 +55,7 @@ TEST(ScudoVectorTest, ReallocateFails) { rlimit Limit = {}; EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit)); - rlimit EmptyLimit = {.rlim_max = Limit.rlim_max}; + rlimit EmptyLimit = {.rlim_cur = 0, .rlim_max = Limit.rlim_max}; EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit)); V.resize(capacity); -- GitLab From abc270ae00cd991bf1b2125e880b9eb73d8d6727 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Wed, 27 Mar 2024 12:39:07 -0700 Subject: [PATCH 112/541] Finish revert "[SystemZ][z/OS] TXT records in the GOFF reader (#74526)" This finishes the revert started in aeb8628c218f8224e08dddcdd3199a445d8607a8 which didn't completely back out the original patch. --- llvm/lib/Object/GOFFObjectFile.cpp | 148 ----------------------------- 1 file changed, 148 deletions(-) diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp index d8e1ddf2aef8..76a13559ebfe 100644 --- a/llvm/lib/Object/GOFFObjectFile.cpp +++ b/llvm/lib/Object/GOFFObjectFile.cpp @@ -394,154 +394,6 @@ GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const { return EsdRecord; } -uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const { - const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); - uint32_t Length; - ESDRecord::getLength(EsdRecord, Length); - if (Length == 0) { - const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec); - if (PrEsdRecord) - EsdRecord = PrEsdRecord; - } - - uint32_t DefEsdId; - ESDRecord::getEsdId(EsdRecord, DefEsdId); - LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n'); - return DefEsdId; -} - -void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { - Sec.d.a++; - if ((Sec.d.a) >= SectionList.size()) - Sec.d.a = 0; -} - -Expected GOFFObjectFile::getSectionName(DataRefImpl Sec) const { - DataRefImpl EdSym; - SectionEntryImpl EsdIds = SectionList[Sec.d.a]; - EdSym.d.a = EsdIds.d.a; - Expected Name = getSymbolName(EdSym); - if (Name) { - StringRef Res = *Name; - LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n'); - LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n'); - Name = Res; - } - return Name; -} - -uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { - uint32_t Offset; - const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); - ESDRecord::getOffset(EsdRecord, Offset); - return Offset; -} - -uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const { - uint32_t Length; - uint32_t DefEsdId = getSectionDefEsdId(Sec); - const uint8_t *EsdRecord = EsdPtrs[DefEsdId]; - ESDRecord::getLength(EsdRecord, Length); - LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n'); - return static_cast(Length); -} - -// Unravel TXT records and expand fill characters to produce -// a contiguous sequence of bytes. -Expected> -GOFFObjectFile::getSectionContents(DataRefImpl Sec) const { - if (SectionDataCache.count(Sec.d.a)) { - auto &Buf = SectionDataCache[Sec.d.a]; - return ArrayRef(Buf); - } - uint64_t SectionSize = getSectionSize(Sec); - uint32_t DefEsdId = getSectionDefEsdId(Sec); - - const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec); - bool FillBytePresent; - ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent); - uint8_t FillByte = '\0'; - if (FillBytePresent) - ESDRecord::getFillByteValue(EdEsdRecord, FillByte); - - // Initialize section with fill byte. - SmallVector Data(SectionSize, FillByte); - - // Replace section with content from text records. - for (const uint8_t *TxtRecordInt : TextPtrs) { - const uint8_t *TxtRecordPtr = TxtRecordInt; - uint32_t TxtEsdId; - TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId); - LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n'); - - if (TxtEsdId != DefEsdId) - continue; - - uint32_t TxtDataOffset; - TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset); - - uint16_t TxtDataSize; - TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize); - - LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size " - << TxtDataSize << "\n"); - - SmallString<256> CompleteData; - CompleteData.reserve(TxtDataSize); - if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData)) - return std::move(Err); - assert(CompleteData.size() == TxtDataSize && "Wrong length of data"); - std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize, - Data.begin() + TxtDataOffset); - } - SectionDataCache[Sec.d.a] = Data; - return ArrayRef(Data); -} - -uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { - const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); - GOFF::ESDAlignment Pow2Alignment; - ESDRecord::getAlignment(EsdRecord, Pow2Alignment); - return 1ULL << static_cast(Pow2Alignment); -} - -bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const { - const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); - GOFF::ESDExecutable Executable; - ESDRecord::getExecutable(EsdRecord, Executable); - return Executable == GOFF::ESD_EXE_CODE; -} - -bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const { - const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); - GOFF::ESDExecutable Executable; - ESDRecord::getExecutable(EsdRecord, Executable); - return Executable == GOFF::ESD_EXE_DATA; -} - -bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const { - const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); - GOFF::ESDLoadingBehavior LoadingBehavior; - ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); - return LoadingBehavior == GOFF::ESD_LB_NoLoad; -} - -bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const { - if (!isSectionData(Sec)) - return false; - - const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec); - GOFF::ESDLoadingBehavior LoadingBehavior; - ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior); - return LoadingBehavior == GOFF::ESD_LB_Initial; -} - -bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const { - // GOFF uses fill characters and fill characters are applied - // on getSectionContents() - so we say false to zero init. - return false; -} - section_iterator GOFFObjectFile::section_begin() const { DataRefImpl Sec; moveSectionNext(Sec); -- GitLab From 0d7ea50d20414e2da3019c45a0a3de804167fa47 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Mar 2024 12:15:17 -0700 Subject: [PATCH 113/541] [AArch64] Pre-commit test for #86717. NFC --- llvm/test/CodeGen/AArch64/pr86717.ll | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/pr86717.ll diff --git a/llvm/test/CodeGen/AArch64/pr86717.ll b/llvm/test/CodeGen/AArch64/pr86717.ll new file mode 100644 index 000000000000..aac0c0df5f51 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/pr86717.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=aarch64 | FileCheck %s + +define <16 x i8> @f(i32 %0) { +; CHECK-LABEL: f: +; CHECK: // %bb.0: +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov w8, #1 // =0x1 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: sub w8, w8, w0 +; CHECK-NEXT: mov w10, #3 // =0x3 +; CHECK-NEXT: orr x8, x9, x8 +; CHECK-NEXT: str q0, [sp] +; CHECK-NEXT: strb w10, [x8] +; CHECK-NEXT: ldr q0, [sp], #16 +; CHECK-NEXT: ret + %2 = sub nuw i32 1, %0 + %3 = insertelement <16 x i8> zeroinitializer, i8 3, i32 %2 + ret <16 x i8> %3 +} -- GitLab From acab142751d3498c6d0aa63253dc1c9f3f83f268 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Mar 2024 11:35:12 -0700 Subject: [PATCH 114/541] [LegalizeDAG] Freeze index when converting insert_elt/insert_subvector to load/store on stack. We try clamp the index to be within the bounds of the stack object we create, but if we don't freeze it, poison can propagate into the clamp code. This can cause the access to leave the bounds of the stack object. We have other instances of this issue in type legalization and extract_elt/subvector, but posting this patch first for direction check. Fixes #86717 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 3 ++ llvm/test/CodeGen/AArch64/pr86717.ll | 6 +-- .../lasx/ir-instruction/insertelement.ll | 42 ++++++++++-------- .../lsx/ir-instruction/insertelement.ll | 42 ++++++++++-------- .../X86/2009-06-05-VariableIndexInsert.ll | 8 ++-- .../CodeGen/X86/insertelement-var-index.ll | 44 ++++++++++--------- 6 files changed, 82 insertions(+), 63 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index e10b8bc8c5e2..24f69ea1b742 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1455,6 +1455,9 @@ SDValue SelectionDAGLegalize::ExpandInsertToVectorThroughStack(SDValue Op) { // First store the whole vector. SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo); + // Freeze the index so we don't poison the clamping code we're about to emit. + Idx = DAG.getFreeze(Idx); + // Then store the inserted part. if (PartVT.isVector()) { SDValue SubStackPtr = diff --git a/llvm/test/CodeGen/AArch64/pr86717.ll b/llvm/test/CodeGen/AArch64/pr86717.ll index aac0c0df5f51..aa8be954be72 100644 --- a/llvm/test/CodeGen/AArch64/pr86717.ll +++ b/llvm/test/CodeGen/AArch64/pr86717.ll @@ -10,10 +10,10 @@ define <16 x i8> @f(i32 %0) { ; CHECK-NEXT: mov w8, #1 // =0x1 ; CHECK-NEXT: mov x9, sp ; CHECK-NEXT: sub w8, w8, w0 -; CHECK-NEXT: mov w10, #3 // =0x3 -; CHECK-NEXT: orr x8, x9, x8 +; CHECK-NEXT: bfxil x9, x8, #0, #4 +; CHECK-NEXT: mov w8, #3 // =0x3 ; CHECK-NEXT: str q0, [sp] -; CHECK-NEXT: strb w10, [x8] +; CHECK-NEXT: strb w8, [x9] ; CHECK-NEXT: ldr q0, [sp], #16 ; CHECK-NEXT: ret %2 = sub nuw i32 1, %0 diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll index 25106b456d2f..6629d3440549 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll @@ -123,9 +123,10 @@ define void @insert_32xi8_idx(ptr %src, ptr %dst, i8 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 0 -; CHECK-NEXT: st.b $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 0 +; CHECK-NEXT: st.b $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -149,9 +150,10 @@ define void @insert_16xi16_idx(ptr %src, ptr %dst, i16 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 1 -; CHECK-NEXT: st.h $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 1 +; CHECK-NEXT: st.h $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -175,9 +177,10 @@ define void @insert_8xi32_idx(ptr %src, ptr %dst, i32 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 2 -; CHECK-NEXT: st.w $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 2 +; CHECK-NEXT: st.w $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -201,9 +204,10 @@ define void @insert_4xi64_idx(ptr %src, ptr %dst, i64 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 3 -; CHECK-NEXT: st.d $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 3 +; CHECK-NEXT: st.d $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -227,9 +231,10 @@ define void @insert_8xfloat_idx(ptr %src, ptr %dst, float %in, i32 %idx) nounwin ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr1, $a0, 0 ; CHECK-NEXT: xvst $xr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 4, 2 -; CHECK-NEXT: fst.s $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 4, 2 +; CHECK-NEXT: fst.s $fa0, $a2, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -253,9 +258,10 @@ define void @insert_4xdouble_idx(ptr %src, ptr %dst, double %in, i32 %idx) nounw ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr1, $a0, 0 ; CHECK-NEXT: xvst $xr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 4, 3 -; CHECK-NEXT: fst.d $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 4, 3 +; CHECK-NEXT: fst.d $fa0, $a2, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll index 7f232073ae12..19171b7d8ed7 100644 --- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll +++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll @@ -87,9 +87,10 @@ define void @insert_16xi8_idx(ptr %src, ptr %dst, i8 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 0 -; CHECK-NEXT: st.b $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 0 +; CHECK-NEXT: st.b $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -106,9 +107,10 @@ define void @insert_8xi16_idx(ptr %src, ptr %dst, i16 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 1 -; CHECK-NEXT: st.h $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 1 +; CHECK-NEXT: st.h $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -125,9 +127,10 @@ define void @insert_4xi32_idx(ptr %src, ptr %dst, i32 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 2 -; CHECK-NEXT: st.w $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 2 +; CHECK-NEXT: st.w $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -144,9 +147,10 @@ define void @insert_2xi64_idx(ptr %src, ptr %dst, i64 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 3 -; CHECK-NEXT: st.d $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 3 +; CHECK-NEXT: st.d $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -163,9 +167,10 @@ define void @insert_4xfloat_idx(ptr %src, ptr %dst, float %ins, i32 %idx) nounwi ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr1, $a0, 0 ; CHECK-NEXT: vst $vr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 3, 2 -; CHECK-NEXT: fst.s $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 3, 2 +; CHECK-NEXT: fst.s $fa0, $a2, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -182,9 +187,10 @@ define void @insert_2xdouble_idx(ptr %src, ptr %dst, double %ins, i32 %idx) noun ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr1, $a0, 0 ; CHECK-NEXT: vst $vr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 3, 3 -; CHECK-NEXT: fst.d $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 3, 3 +; CHECK-NEXT: fst.d $fa0, $a2, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 diff --git a/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll b/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll index 535450a52ff6..695a2d0cd806 100644 --- a/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll +++ b/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll @@ -9,11 +9,11 @@ define <2 x i64> @_mm_insert_epi16(<2 x i64> %a, i32 %b, i32 %imm) nounwind read ; X86-NEXT: movl %esp, %ebp ; X86-NEXT: andl $-16, %esp ; X86-NEXT: subl $32, %esp -; X86-NEXT: movzwl 8(%ebp), %eax -; X86-NEXT: movl 12(%ebp), %ecx -; X86-NEXT: andl $7, %ecx +; X86-NEXT: movl 12(%ebp), %eax +; X86-NEXT: movzwl 8(%ebp), %ecx +; X86-NEXT: andl $7, %eax ; X86-NEXT: movaps %xmm0, (%esp) -; X86-NEXT: movw %ax, (%esp,%ecx,2) +; X86-NEXT: movw %cx, (%esp,%eax,2) ; X86-NEXT: movaps (%esp), %xmm0 ; X86-NEXT: movl %ebp, %esp ; X86-NEXT: popl %ebp diff --git a/llvm/test/CodeGen/X86/insertelement-var-index.ll b/llvm/test/CodeGen/X86/insertelement-var-index.ll index 8ed8495d7a46..5420e6b5ce86 100644 --- a/llvm/test/CodeGen/X86/insertelement-var-index.ll +++ b/llvm/test/CodeGen/X86/insertelement-var-index.ll @@ -1009,18 +1009,19 @@ define <2 x i64> @arg_i64_v2i64(<2 x i64> %v, i64 %x, i32 %y) nounwind { ; X86AVX2-NEXT: pushl %esi ; X86AVX2-NEXT: andl $-16, %esp ; X86AVX2-NEXT: subl $48, %esp -; X86AVX2-NEXT: movl 8(%ebp), %eax -; X86AVX2-NEXT: movl 12(%ebp), %ecx -; X86AVX2-NEXT: movl 16(%ebp), %edx +; X86AVX2-NEXT: movl 8(%ebp), %edx +; X86AVX2-NEXT: movl 12(%ebp), %eax +; X86AVX2-NEXT: movl 16(%ebp), %ecx ; X86AVX2-NEXT: vmovaps %xmm0, (%esp) -; X86AVX2-NEXT: leal (%edx,%edx), %esi +; X86AVX2-NEXT: addl %ecx, %ecx +; X86AVX2-NEXT: movl %ecx, %esi ; X86AVX2-NEXT: andl $3, %esi -; X86AVX2-NEXT: movl %eax, (%esp,%esi,4) +; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %xmm0 ; X86AVX2-NEXT: vmovaps %xmm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%edx,%edx), %eax -; X86AVX2-NEXT: andl $3, %eax -; X86AVX2-NEXT: movl %ecx, 16(%esp,%eax,4) +; X86AVX2-NEXT: incl %ecx +; X86AVX2-NEXT: andl $3, %ecx +; X86AVX2-NEXT: movl %eax, 16(%esp,%ecx,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %xmm0 ; X86AVX2-NEXT: leal -4(%ebp), %esp ; X86AVX2-NEXT: popl %esi @@ -1362,12 +1363,13 @@ define <2 x i64> @load_i64_v2i64(<2 x i64> %v, ptr %p, i32 %y) nounwind { ; X86AVX2-NEXT: movl (%ecx), %edx ; X86AVX2-NEXT: movl 4(%ecx), %ecx ; X86AVX2-NEXT: vmovaps %xmm0, (%esp) -; X86AVX2-NEXT: leal (%eax,%eax), %esi +; X86AVX2-NEXT: addl %eax, %eax +; X86AVX2-NEXT: movl %eax, %esi ; X86AVX2-NEXT: andl $3, %esi ; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %xmm0 ; X86AVX2-NEXT: vmovaps %xmm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%eax,%eax), %eax +; X86AVX2-NEXT: incl %eax ; X86AVX2-NEXT: andl $3, %eax ; X86AVX2-NEXT: movl %ecx, 16(%esp,%eax,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %xmm0 @@ -1742,18 +1744,19 @@ define <4 x i64> @arg_i64_v4i64(<4 x i64> %v, i64 %x, i32 %y) nounwind { ; X86AVX2-NEXT: pushl %esi ; X86AVX2-NEXT: andl $-32, %esp ; X86AVX2-NEXT: subl $96, %esp -; X86AVX2-NEXT: movl 8(%ebp), %eax -; X86AVX2-NEXT: movl 12(%ebp), %ecx -; X86AVX2-NEXT: movl 16(%ebp), %edx +; X86AVX2-NEXT: movl 8(%ebp), %edx +; X86AVX2-NEXT: movl 12(%ebp), %eax +; X86AVX2-NEXT: movl 16(%ebp), %ecx ; X86AVX2-NEXT: vmovaps %ymm0, (%esp) -; X86AVX2-NEXT: leal (%edx,%edx), %esi +; X86AVX2-NEXT: addl %ecx, %ecx +; X86AVX2-NEXT: movl %ecx, %esi ; X86AVX2-NEXT: andl $7, %esi -; X86AVX2-NEXT: movl %eax, (%esp,%esi,4) +; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %ymm0 ; X86AVX2-NEXT: vmovaps %ymm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%edx,%edx), %eax -; X86AVX2-NEXT: andl $7, %eax -; X86AVX2-NEXT: movl %ecx, 32(%esp,%eax,4) +; X86AVX2-NEXT: incl %ecx +; X86AVX2-NEXT: andl $7, %ecx +; X86AVX2-NEXT: movl %eax, 32(%esp,%ecx,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %ymm0 ; X86AVX2-NEXT: leal -4(%ebp), %esp ; X86AVX2-NEXT: popl %esi @@ -2128,12 +2131,13 @@ define <4 x i64> @load_i64_v4i64(<4 x i64> %v, ptr %p, i32 %y) nounwind { ; X86AVX2-NEXT: movl (%ecx), %edx ; X86AVX2-NEXT: movl 4(%ecx), %ecx ; X86AVX2-NEXT: vmovaps %ymm0, (%esp) -; X86AVX2-NEXT: leal (%eax,%eax), %esi +; X86AVX2-NEXT: addl %eax, %eax +; X86AVX2-NEXT: movl %eax, %esi ; X86AVX2-NEXT: andl $7, %esi ; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %ymm0 ; X86AVX2-NEXT: vmovaps %ymm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%eax,%eax), %eax +; X86AVX2-NEXT: incl %eax ; X86AVX2-NEXT: andl $7, %eax ; X86AVX2-NEXT: movl %ecx, 32(%esp,%eax,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %ymm0 -- GitLab From 4d4626d9d59bce9f4d19bd4a1b384f1122904419 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 13:10:42 -0700 Subject: [PATCH 115/541] [TEST][HWASAN] Fix test after #86771 --- .../test/Instrumentation/HWAddressSanitizer/globals-access.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll index c83911f60149..184f84d2859a 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --global-value-regex "x" --version 4 -; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64 -hwasan-globals=0 | FileCheck %s --check-prefixes=NOGLOB -; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64 -hwasan-globals=1 | FileCheck %s +; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64-linux-gnu -hwasan-globals=0 | FileCheck %s --check-prefixes=NOGLOB +; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64-linux-gnu -hwasan-globals=1 | FileCheck %s @x = dso_local global i32 0, align 4 -- GitLab From 3522de9e412fbaa6d7344cc31bd43d1be6c95d59 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 13:19:00 -0700 Subject: [PATCH 116/541] [TEST][HWASAN] Fix test after #86771 --- llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll index 184f84d2859a..f8d13fc4237e 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll @@ -2,6 +2,8 @@ ; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64-linux-gnu -hwasan-globals=0 | FileCheck %s --check-prefixes=NOGLOB ; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64-linux-gnu -hwasan-globals=1 | FileCheck %s +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + @x = dso_local global i32 0, align 4 ;. -- GitLab From fa90a0aa0e12aaf657d0f6f7626e05f90ba6f999 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Wed, 27 Mar 2024 13:24:53 -0700 Subject: [PATCH 117/541] [llvm-exegesis] Improve error handling for shm_open calls This patch adds error handling for shm_open failures in one case where they were not handled before and also makes an error handler in another case report the value of errno for diagnosis. --- llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index 1fd81bd407be..0a947f6e206f 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -63,6 +63,10 @@ Error SubprocessMemory::addMemoryDefinition( SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (SharedMemoryFD == -1) + return make_error( + "Failed to create shared memory object for memory definition: " + + Twine(strerror(errno))); if (ftruncate(SharedMemoryFD, MemVal.SizeBytes) != 0) { return make_error("Truncating a memory definiton failed: " + Twine(strerror(errno))); @@ -100,7 +104,8 @@ Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFileDescriptor == -1) return make_error( - "Getting file descriptor for auxiliary memory failed"); + "Getting file descriptor for auxiliary memory failed: " + + Twine(strerror(errno))); // set up memory value file descriptors int *AuxiliaryMemoryMapping = (int *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, -- GitLab From 8a071678a9091d536eae29912ca7be6238105956 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Wed, 27 Mar 2024 13:28:26 -0700 Subject: [PATCH 118/541] Revert "[libc][math][c23] Add remaining linux/* entrypoints for {,u}fromfp{,x}* (#86692)" This reverts commit cd17082b24079a31eff0057abe407da5cfb7b0fc because the newly added tests fail on 32b ARM. Link: #86692 Link: https://lab.llvm.org/buildbot/#/builders/229/builds/24458 --- libc/config/linux/aarch64/entrypoints.txt | 16 ------------ libc/config/linux/arm/entrypoints.txt | 12 --------- libc/config/linux/riscv/entrypoints.txt | 16 ------------ libc/docs/math/index.rst | 32 +++++++++++------------ 4 files changed, 16 insertions(+), 60 deletions(-) diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index ab0be7e35dce..78da7f0b334b 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -396,12 +396,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl - libc.src.math.fromfp - libc.src.math.fromfpf - libc.src.math.fromfpl - libc.src.math.fromfpx - libc.src.math.fromfpxf - libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -484,12 +478,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl - libc.src.math.ufromfp - libc.src.math.ufromfpf - libc.src.math.ufromfpl - libc.src.math.ufromfpx - libc.src.math.ufromfpxf - libc.src.math.ufromfpxl ) if(LIBC_TYPES_HAS_FLOAT128) @@ -512,8 +500,6 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 - libc.src.math.fromfpf128 - libc.src.math.fromfpxf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 @@ -531,8 +517,6 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 - libc.src.math.ufromfpf128 - libc.src.math.ufromfpxf128 ) endif() diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 1d9d5ed67200..6e63e270280e 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -263,12 +263,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl - libc.src.math.fromfp - libc.src.math.fromfpf - libc.src.math.fromfpl - libc.src.math.fromfpx - libc.src.math.fromfpxf - libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -351,12 +345,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl - libc.src.math.ufromfp - libc.src.math.ufromfpf - libc.src.math.ufromfpl - libc.src.math.ufromfpx - libc.src.math.ufromfpxf - libc.src.math.ufromfpxl ) set(TARGET_LLVMLIBC_ENTRYPOINTS diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 96acd999efda..5aae4e246cfb 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -404,12 +404,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl - libc.src.math.fromfp - libc.src.math.fromfpf - libc.src.math.fromfpl - libc.src.math.fromfpx - libc.src.math.fromfpxf - libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -492,12 +486,6 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl - libc.src.math.ufromfp - libc.src.math.ufromfpf - libc.src.math.ufromfpl - libc.src.math.ufromfpx - libc.src.math.ufromfpxf - libc.src.math.ufromfpxl ) if(LIBC_TYPES_HAS_FLOAT128) @@ -520,8 +508,6 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 - libc.src.math.fromfpf128 - libc.src.math.fromfpxf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 @@ -539,8 +525,6 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 - libc.src.math.ufromfpf128 - libc.src.math.ufromfpxf128 ) endif() diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index d8dee3c90619..080b6a4427f5 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -190,21 +190,21 @@ Basic Operations +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | frexpf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfp | |check| | |check| | |check| | |check| | | | | | | | | | +| fromfp | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpf | |check| | |check| | |check| | |check| | | | | | | | | | +| fromfpf | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpl | |check| | |check| | |check| | |check| | | | | | | | | | +| fromfpl | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpf128 | |check| | |check| | | |check| | | | | | | | | | +| fromfpf128 | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpx | |check| | |check| | |check| | |check| | | | | | | | | | +| fromfpx | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpxf | |check| | |check| | |check| | |check| | | | | | | | | | +| fromfpxf | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpxl | |check| | |check| | |check| | |check| | | | | | | | | | +| fromfpxl | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fromfpxf128 | |check| | |check| | | |check| | | | | | | | | | +| fromfpxf128 | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | ilogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ @@ -364,21 +364,21 @@ Basic Operations +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | truncf128 | |check| | |check| | | |check| | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfp | |check| | |check| | |check| | |check| | | | | | | | | | +| ufromfp | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpf | |check| | |check| | |check| | |check| | | | | | | | | | +| ufromfpf | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpl | |check| | |check| | |check| | |check| | | | | | | | | | +| ufromfpl | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpf128 | |check| | |check| | | |check| | | | | | | | | | +| ufromfpf128 | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpx | |check| | |check| | |check| | |check| | | | | | | | | | +| ufromfpx | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpxf | |check| | |check| | |check| | |check| | | | | | | | | | +| ufromfpxf | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpxl | |check| | |check| | |check| | |check| | | | | | | | | | +| ufromfpxl | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ufromfpxf128 | |check| | |check| | | |check| | | | | | | | | | +| ufromfpxf128 | |check| | | | | | | | | | | | | +------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -- GitLab From 453a63caebc35378bcdb31da9d0f358a3998e51b Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 13:38:21 -0700 Subject: [PATCH 119/541] [NFC][HWASAN] Promote InstrumentGlobals to member (#86773) --- llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 5d366e3d6dee..96fd530be333 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -422,6 +422,7 @@ private: bool InstrumentLandingPads; bool InstrumentWithCalls; bool InstrumentStack; + bool InstrumentGlobals; bool DetectUseAfterScope; bool UsePageAliases; bool UseMatchAllCallback; @@ -639,11 +640,13 @@ void HWAddressSanitizer::initializeModule() { // If we don't have personality function support, fall back to landing pads. InstrumentLandingPads = optOr(ClInstrumentLandingPads, !NewRuntime); + InstrumentGlobals = + !CompileKernel && !UsePageAliases && optOr(ClGlobals, NewRuntime); + if (!CompileKernel) { createHwasanCtorComdat(); - bool InstrumentGlobals = optOr(ClGlobals, NewRuntime); - if (InstrumentGlobals && !UsePageAliases) + if (InstrumentGlobals) instrumentGlobals(); bool InstrumentPersonalityFunctions = -- GitLab From 70e8cf0c31493071c50c8112c6e0c7903abf6ca6 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 13:43:18 -0700 Subject: [PATCH 120/541] [HWASAN] Don't instrument loads from global if globals are not tagged (#86774) --- .../Instrumentation/HWAddressSanitizer.cpp | 7 +++++++ .../HWAddressSanitizer/globals-access.ll | 16 ---------------- .../HWAddressSanitizer/use-after-scope-setjmp.ll | 1 - 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 96fd530be333..f7d4803ded15 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -790,6 +790,13 @@ bool HWAddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) { if (SSI && SSI->stackAccessIsSafe(*Inst)) return true; } + + if (isa(getUnderlyingObject(Ptr))) { + if (!InstrumentGlobals) + return true; + // TODO: Optimize inbound global accesses, like Asan `instrumentMop`. + } + return false; } diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll index f8d13fc4237e..f9040afd1c01 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll @@ -15,22 +15,6 @@ define dso_local noundef i32 @_Z3tmpv() sanitize_hwaddress { ; NOGLOB-LABEL: define dso_local noundef i32 @_Z3tmpv( ; NOGLOB-SAME: ) #[[ATTR0:[0-9]+]] { ; NOGLOB-NEXT: entry: -; NOGLOB-NEXT: [[TMP12:%.*]] = load i64, ptr @__hwasan_tls, align 8 -; NOGLOB-NEXT: [[TMP1:%.*]] = or i64 [[TMP12]], 4294967295 -; NOGLOB-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP1]], 1 -; NOGLOB-NEXT: [[TMP2:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr -; NOGLOB-NEXT: [[TMP3:%.*]] = lshr i64 ptrtoint (ptr @x to i64), 56 -; NOGLOB-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i8 -; NOGLOB-NEXT: [[TMP5:%.*]] = and i64 ptrtoint (ptr @x to i64), 72057594037927935 -; NOGLOB-NEXT: [[TMP6:%.*]] = lshr i64 [[TMP5]], 4 -; NOGLOB-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP2]], i64 [[TMP6]] -; NOGLOB-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1 -; NOGLOB-NEXT: [[TMP9:%.*]] = icmp ne i8 [[TMP4]], [[TMP8]] -; NOGLOB-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP11:%.*]], !prof [[PROF1:![0-9]+]] -; NOGLOB: 10: -; NOGLOB-NEXT: call void @llvm.hwasan.check.memaccess.shortgranules(ptr [[TMP2]], ptr @x, i32 2) -; NOGLOB-NEXT: br label [[TMP11]] -; NOGLOB: 11: ; NOGLOB-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 ; NOGLOB-NEXT: ret i32 [[TMP0]] ; diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll index 079d72241283..62fd7a167156 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll @@ -54,7 +54,6 @@ define dso_local noundef i1 @_Z6targetv() sanitize_hwaddress { ; CHECK: sw.bb1: ; CHECK-NEXT: br label [[RETURN]] ; CHECK: while.body: -; CHECK-NEXT: call void @llvm.hwasan.check.memaccess(ptr [[TMP16]], ptr @stackbuf, i32 19) ; CHECK-NEXT: store ptr [[BUF_HWASAN]], ptr @stackbuf, align 8 ; CHECK-NEXT: call void @may_jump() ; CHECK-NEXT: br label [[RETURN]] -- GitLab From f18600c87404eab8d0a279b0286f8add8b4a1bb8 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 27 Mar 2024 13:50:17 -0700 Subject: [PATCH 121/541] [Driver] Avoid repeated ToolChain.getTriple() calls. NFC --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 6b1fbba7abd0..ace4fb99581e 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -758,15 +758,15 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC, void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfo &Input, bool IsThinLTO) { - const bool IsOSAIX = ToolChain.getTriple().isOSAIX(); - const bool IsAMDGCN = ToolChain.getTriple().isAMDGCN(); + const llvm::Triple &Triple = ToolChain.getTriple(); + const bool IsOSAIX = Triple.isOSAIX(); + const bool IsAMDGCN = Triple.isAMDGCN(); const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); const Driver &D = ToolChain.getDriver(); const bool IsFatLTO = Args.hasArg(options::OPT_ffat_lto_objects); const bool IsUnifiedLTO = Args.hasArg(options::OPT_funified_lto); if (llvm::sys::path::filename(Linker) != "ld.lld" && - llvm::sys::path::stem(Linker) != "ld.lld" && - !ToolChain.getTriple().isOSOpenBSD()) { + llvm::sys::path::stem(Linker) != "ld.lld" && !Triple.isOSOpenBSD()) { // Tell the linker to load the plugin. This has to come before // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to // come before any -plugin-opt/-bplugin_opt that -Wl might forward. @@ -835,7 +835,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, // the plugin. // Handle flags for selecting CPU variants. - std::string CPU = getCPUName(D, Args, ToolChain.getTriple()); + std::string CPU = getCPUName(D, Args, Triple); if (!CPU.empty()) CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "mcpu=" + CPU)); @@ -966,10 +966,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, bool HasRoptr = Args.hasFlag(options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr, false); StringRef OptStr = HasRoptr ? "-mxcoff-roptr" : "-mno-xcoff-roptr"; - if (!IsOSAIX) D.Diag(diag::err_drv_unsupported_opt_for_target) - << OptStr << ToolChain.getTriple().str(); + << OptStr << Triple.str(); if (HasRoptr) { // The data sections option is on by default on AIX. We only need to error @@ -1032,7 +1031,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, } if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, - ToolChain.getTriple().hasDefaultEmulatedTLS())) { + Triple.hasDefaultEmulatedTLS())) { CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + "-emulated-tls")); } -- GitLab From c7d947f5e6c966bdba4db26097c3b433fcbe7841 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Wed, 27 Mar 2024 13:59:35 -0700 Subject: [PATCH 122/541] [lldb] [ObjC runtime] Don't cast to signed when left shifting (#86605) This is fixing a report from ubsan which I don't think is super high value, but our testsuite hits it on TestDataFormatterObjCNSContainer.py so I'd like to work around it. We are getting ``` runtime error: left shift of negative value -8827055269646171913 3159 int64_t data_payload_signed = 3160 ((int64_t)((int64_t)unobfuscated -> 3161 << m_objc_debug_taggedpointer_ext_payload_lshift) >> 3162 m_objc_debug_taggedpointer_ext_payload_rshift); ``` At this point `unobfuscated` is 0x85800000000000f7 and `m_objc_debug_taggedpointer_ext_payload_lshift` is 9, so `(int64_t)0x85800000000000f7<<9` shifts off the "sign" bit and then some zeroes etc, and that's how we get this error. We're only trying to extract some bits in the middle of the doubleword, so the fact that we're "losing" the sign is not a bug. Change the inner cast to (uint64_t). --- .../ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 3e5ee6f66373..d3fc487aed43 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -3154,7 +3154,7 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift); int64_t data_payload_signed = - ((int64_t)((int64_t)unobfuscated + ((int64_t)((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift); -- GitLab From acdba090f2724335cf6cf6ecbfb68f67f0cd2def Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 27 Mar 2024 14:08:59 -0700 Subject: [PATCH 123/541] [ELF] Change duplicate symbol errors to use errorOrWarn so that --noinhibit-exec downgrades the error to a warning, which matches GNU ld. Most recoverable errors should use errorOrWarn. --- lld/ELF/Symbols.cpp | 6 +++--- lld/test/ELF/allow-multiple-definition.s | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index cd2b9e22ab32..93653def328f 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -539,8 +539,8 @@ void elf::reportDuplicate(const Symbol &sym, const InputFile *newFile, if (!d->section && !errSec && errOffset && d->value == errOffset) return; if (!d->section || !errSec) { - error("duplicate symbol: " + toString(sym) + "\n>>> defined in " + - toString(sym.file) + "\n>>> defined in " + toString(newFile)); + errorOrWarn("duplicate symbol: " + toString(sym) + "\n>>> defined in " + + toString(sym.file) + "\n>>> defined in " + toString(newFile)); return; } @@ -564,7 +564,7 @@ void elf::reportDuplicate(const Symbol &sym, const InputFile *newFile, if (!src2.empty()) msg += src2 + "\n>>> "; msg += obj2; - error(msg); + errorOrWarn(msg); } void Symbol::checkDuplicate(const Defined &other) const { diff --git a/lld/test/ELF/allow-multiple-definition.s b/lld/test/ELF/allow-multiple-definition.s index 492784a3601d..96fa2627e1bf 100644 --- a/lld/test/ELF/allow-multiple-definition.s +++ b/lld/test/ELF/allow-multiple-definition.s @@ -9,6 +9,9 @@ # RUN: llvm-objdump --no-print-imm-hex -d %t3 | FileCheck %s # RUN: llvm-objdump --no-print-imm-hex -d %t4 | FileCheck --check-prefix=REVERT %s +# RUN: ld.lld --noinhibit-exec %t2 %t1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN +# WARN: warning: duplicate symbol: _bar + # RUN: ld.lld -z muldefs --fatal-warnings %t1 %t2 -o %t3 # RUN: ld.lld -z muldefs --fatal-warnings %t2 %t1 -o %t4 # RUN: llvm-objdump --no-print-imm-hex -d %t3 | FileCheck %s -- GitLab From b9cd48f96acdd07c627ccafbf4386a1f3dcd6c51 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 27 Mar 2024 21:22:15 +0000 Subject: [PATCH 124/541] Revert "[TBAA] Add verifier for tbaa.struct metadata (#86709)" This reverts commit df75183d70e029352a49c93f275db703c81a65c1. Revert for now as this appears to cause failures on some buildbots, e.g.: https://lab.llvm.org/buildbot/#/builders/93/builds/19428/steps/10/logs/stdio --- llvm/include/llvm/IR/Verifier.h | 1 - llvm/lib/IR/Verifier.cpp | 32 ------------------- llvm/test/CodeGen/AArch64/arm64-abi_align.ll | 4 +-- .../AMDGPU/mem-intrinsics.ll | 2 +- .../InstCombine/struct-assign-tbaa.ll | 2 +- llvm/test/Transforms/SROA/tbaa-struct3.ll | 2 +- .../Scalarizer/basic-inseltpoison.ll | 3 +- llvm/test/Transforms/Scalarizer/basic.ll | 3 +- llvm/test/Verifier/tbaa-struct.ll | 14 ++------ 9 files changed, 9 insertions(+), 54 deletions(-) diff --git a/llvm/include/llvm/IR/Verifier.h b/llvm/include/llvm/IR/Verifier.h index b7db6e0bbfb7..b25f8eb77ee3 100644 --- a/llvm/include/llvm/IR/Verifier.h +++ b/llvm/include/llvm/IR/Verifier.h @@ -77,7 +77,6 @@ public: /// Visit an instruction and return true if it is valid, return false if an /// invalid TBAA is attached. bool visitTBAAMetadata(Instruction &I, const MDNode *MD); - bool visitTBAAStructMetadata(Instruction &I, const MDNode *MD); }; /// Check a function for errors, useful for use when debugging a diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index e16572540f96..33f358440a31 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5096,9 +5096,6 @@ void Verifier::visitInstruction(Instruction &I) { if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); - if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa_struct)) - TBAAVerifyHelper.visitTBAAStructMetadata(I, TBAA); - if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias)) visitAliasScopeListMetadata(MD); if (MDNode *MD = I.getMetadata(LLVMContext::MD_alias_scope)) @@ -7422,35 +7419,6 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { return true; } -bool TBAAVerifier::visitTBAAStructMetadata(Instruction &I, const MDNode *MD) { - CheckTBAA(MD->getNumOperands() % 3 == 0, - "tbaa.struct operands must occur in groups of three", &I, MD); - - // Each group of three operands must consist of two integers and a - // tbaa node. Moreover, the regions described by the offset and size - // operands must be non-overlapping. - std::optional NextFree; - for (unsigned int Idx = 0; Idx < MD->getNumOperands(); Idx += 3) { - auto *OffsetCI = - mdconst::dyn_extract_or_null(MD->getOperand(Idx)); - CheckTBAA(OffsetCI, "Offset must be a constant integer", &I, MD); - - auto *SizeCI = - mdconst::dyn_extract_or_null(MD->getOperand(Idx + 1)); - CheckTBAA(SizeCI, "Size must be a constant integer", &I, MD); - - MDNode *TBAA = dyn_cast_or_null(MD->getOperand(Idx + 2)); - CheckTBAA(TBAA, "TBAA tag missing", &I, MD); - visitTBAAMetadata(I, TBAA); - - bool NonOverlapping = !NextFree || NextFree->ule(OffsetCI->getValue()); - CheckTBAA(NonOverlapping, "Overlapping tbaa.struct regions", &I, MD); - - NextFree = OffsetCI->getValue() + SizeCI->getValue(); - } - return true; -} - char VerifierLegacyPass::ID = 0; INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false) diff --git a/llvm/test/CodeGen/AArch64/arm64-abi_align.ll b/llvm/test/CodeGen/AArch64/arm64-abi_align.ll index c9fd2d38e27a..089e171e5a4a 100644 --- a/llvm/test/CodeGen/AArch64/arm64-abi_align.ll +++ b/llvm/test/CodeGen/AArch64/arm64-abi_align.ll @@ -518,6 +518,4 @@ attributes #5 = { nobuiltin } !1 = !{!"omnipotent char", !2} !2 = !{!"Simple C/C++ TBAA"} !3 = !{!"short", !1} -!4 = !{i64 0, i64 4, !5, i64 4, i64 2, !6, i64 8, i64 4, !5, i64 12, i64 2, !6, i64 16, i64 4, !5, i64 20, i64 2, !6} -!5 = !{!0, !0, i64 0} -!6 = !{!3, !3, i64 0} +!4 = !{i64 0, i64 4, !0, i64 4, i64 2, !3, i64 8, i64 4, !0, i64 12, i64 2, !3, i64 16, i64 4, !0, i64 20, i64 2, !3} diff --git a/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll index 2f264a2432fc..50b0e7a0f547 100644 --- a/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll +++ b/llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll @@ -141,4 +141,4 @@ attributes #1 = { argmemonly nounwind } !5 = distinct !{!5, !"some domain"} !6 = !{!7} !7 = distinct !{!7, !5, !"some scope 2"} -!8 = !{i64 0, i64 8, !0} +!8 = !{i64 0, i64 8, null} diff --git a/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll b/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll index d079c03f1dcb..996d2c0e67e1 100644 --- a/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll +++ b/llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll @@ -75,7 +75,7 @@ entry: !1 = !{!"omnipotent char", !0} !2 = !{!5, !5, i64 0} !3 = !{i64 0, i64 4, !2} -!4 = !{i64 0, i64 8, !2} +!4 = !{i64 0, i64 8, null} !5 = !{!"float", !0} !6 = !{i64 0, i64 4, !2, i64 4, i64 4, !2} !7 = !{i64 0, i64 2, !2, i64 4, i64 6, !2} diff --git a/llvm/test/Transforms/SROA/tbaa-struct3.ll b/llvm/test/Transforms/SROA/tbaa-struct3.ll index 61034de81e4b..0fcd787fef97 100644 --- a/llvm/test/Transforms/SROA/tbaa-struct3.ll +++ b/llvm/test/Transforms/SROA/tbaa-struct3.ll @@ -539,7 +539,7 @@ declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias !6 = !{!5, !5, i64 0} !7 = !{i64 0, i64 8, !6, i64 8, i64 4, !1} !8 = !{i64 0, i64 4, !1, i64 4, i64 8, !6} -!9 = !{i64 0, i64 8, !6, i64 8, i64 8, !1} +!9 = !{i64 0, i64 8, !6, i64 4, i64 8, !1} !10 = !{i64 0, i64 2, !1, i64 2, i64 2, !1} !11 = !{i64 0, i64 1, !1, i64 1, i64 3, !1} !12 = !{i64 0, i64 2, !1, i64 2, i64 6, !1} diff --git a/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll b/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll index 73ae66dd76c6..bbcdcb6f5867 100644 --- a/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll +++ b/llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll @@ -836,6 +836,5 @@ define <2 x i32> @f23_crash(<2 x i32> %srcvec, i32 %v1) { !2 = !{ !"set2", !0 } !3 = !{ !3, !{!"llvm.loop.parallel_accesses", !13} } !4 = !{ float 4.0 } -!5 = !{ i64 0, i64 8, !6 } -!6 = !{ !1, !1, i64 0 } +!5 = !{ i64 0, i64 8, null } !13 = distinct !{} diff --git a/llvm/test/Transforms/Scalarizer/basic.ll b/llvm/test/Transforms/Scalarizer/basic.ll index 87a70ccd3fc7..db7c5f535f7e 100644 --- a/llvm/test/Transforms/Scalarizer/basic.ll +++ b/llvm/test/Transforms/Scalarizer/basic.ll @@ -870,6 +870,5 @@ define <2 x float> @f25(<2 x float> %src) { !2 = !{ !"set2", !0 } !3 = !{ !3, !{!"llvm.loop.parallel_accesses", !13} } !4 = !{ float 4.0 } -!5 = !{ i64 0, i64 8, !6 } -!6 = !{ !1, !1, i64 0 } +!5 = !{ i64 0, i64 8, null } !13 = distinct !{} diff --git a/llvm/test/Verifier/tbaa-struct.ll b/llvm/test/Verifier/tbaa-struct.ll index 14c19a19d5ae..b8ddc7cee496 100644 --- a/llvm/test/Verifier/tbaa-struct.ll +++ b/llvm/test/Verifier/tbaa-struct.ll @@ -1,36 +1,28 @@ -; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; RUN: llvm-as < %s 2>&1 + +; FIXME: The verifer should reject the invalid !tbaa.struct nodes below. define void @test_overlapping_regions(ptr %a1) { -; CHECK: Overlapping tbaa.struct regions -; CHECK-NEXT: %ld = load i8, ptr %a1, align 1, !tbaa.struct !0 %ld = load i8, ptr %a1, align 1, !tbaa.struct !0 ret void } define void @test_size_not_integer(ptr %a1) { -; CHECK: Size must be a constant integer -; CHECK-NEXT: store i8 1, ptr %a1, align 1, !tbaa.struct !5 store i8 1, ptr %a1, align 1, !tbaa.struct !5 ret void } define void @test_offset_not_integer(ptr %a1, ptr %a2) { -; CHECK: Offset must be a constant integer -; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !6 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !6 ret void } define void @test_tbaa_missing(ptr %a1, ptr %a2) { -; CHECK: TBAA tag missing -; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !7 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !7 ret void } define void @test_tbaa_invalid(ptr %a1) { -; CHECK: Old-style TBAA is no longer allowed, use struct-path TBAA instead -; CHECK-NEXT: store i8 1, ptr %a1, align 1, !tbaa.struct !8 store i8 1, ptr %a1, align 1, !tbaa.struct !8 ret void } -- GitLab From 552c8eb731a1fabef4d81e2a69911506adf39e22 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 27 Mar 2024 14:25:30 -0700 Subject: [PATCH 125/541] [SLP][NFC]Add a test with the wrong result extension after reduction, NFC. --- .../reduction-extension-after-bitwidth.ll | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll new file mode 100644 index 000000000000..611003a55d73 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll @@ -0,0 +1,33 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=riscv64-unknown-linux-gnu -mattr="+v" --passes=slp-vectorizer < %s | FileCheck %s + +define i32 @test(ptr %0, ptr %1) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LOAD_5:%.*]] = load i32, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> ) +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[TMP2]] to i32 +; CHECK-NEXT: [[OP_RDX:%.*]] = and i32 [[TMP3]], [[LOAD_5]] +; CHECK-NEXT: ret i32 [[OP_RDX]] +; +entry: + %zext.0 = zext i8 1 to i32 + %zext.1 = zext i8 1 to i32 + %zext.2 = zext i8 1 to i32 + %zext.3 = zext i8 1 to i32 + %select.zext.0 = select i1 false, i32 -1, i32 %zext.0 + %select.zext.1 = select i1 false, i32 0, i32 %zext.1 + %select.zext.2 = select i1 false, i32 0, i32 %zext.2 + %select.zext.3 = select i1 false, i32 0, i32 %zext.3 + + %load.5 = load i32, ptr %1, align 4 + + %and.0 = and i32 %load.5, %select.zext.0 + %and.1 = and i32 %and.0, %select.zext.1 + %and.2 = and i32 %and.1, %select.zext.2 + %and.3 = and i32 %and.2, %select.zext.3 + + ret i32 %and.3 +} + -- GitLab From 742a82a729925dc79641beb649f492003be40725 Mon Sep 17 00:00:00 2001 From: alx32 <103613512+alx32@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:34:27 -0700 Subject: [PATCH 126/541] [lld-macho] Implement support for ObjC relative method lists (#86231) The MachO format supports relative offsets for ObjC method lists. This support is present already in ld64. With this change we implement this support in lld also. Relative method lists can be identified by a specific flag (0x80000000) in the method list header. When this flag is present, the method list will contain 32-bit relative offsets to the current Program Counter (PC), instead of absolute pointers. Additionally, when relative method lists are used, the offset to the selector name will now be relative and point to the selector reference (selref) instead of the name itself. --- lld/MachO/Config.h | 1 + lld/MachO/Driver.cpp | 17 ++ lld/MachO/InputSection.cpp | 8 + lld/MachO/InputSection.h | 1 + lld/MachO/MapFile.cpp | 22 +- lld/MachO/ObjC.h | 2 + lld/MachO/Options.td | 6 + lld/MachO/SyntheticSections.cpp | 236 +++++++++++++++++ lld/MachO/SyntheticSections.h | 49 ++++ lld/MachO/Writer.cpp | 3 + .../MachO/objc-relative-method-lists-simple.s | 245 ++++++++++++++++++ 11 files changed, 583 insertions(+), 7 deletions(-) create mode 100644 lld/test/MachO/objc-relative-method-lists-simple.s diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h index f820513a111e..7b45f7f4c39a 100644 --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -135,6 +135,7 @@ struct Configuration { bool emitEncryptionInfo = false; bool emitInitOffsets = false; bool emitChainedFixups = false; + bool emitRelativeMethodLists = false; bool thinLTOEmitImportsFiles; bool thinLTOEmitIndexFiles; bool thinLTOIndexOnly; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 14c111ce9685..65de531db04b 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1086,6 +1086,22 @@ static bool shouldEmitChainedFixups(const InputArgList &args) { return isRequested; } +static bool shouldEmitRelativeMethodLists(const InputArgList &args) { + const Arg *arg = args.getLastArg(OPT_objc_relative_method_lists, + OPT_no_objc_relative_method_lists); + if (arg && arg->getOption().getID() == OPT_objc_relative_method_lists) + return true; + if (arg && arg->getOption().getID() == OPT_no_objc_relative_method_lists) + return false; + + // TODO: If no flag is specified, don't default to false, but instead: + // - default false on < ios14 + // - default true on >= ios14 + // For now, until this feature is confirmed stable, default to false if no + // flag is explicitly specified + return false; +} + void SymbolPatterns::clear() { literals.clear(); globs.clear(); @@ -1630,6 +1646,7 @@ bool link(ArrayRef argsArr, llvm::raw_ostream &stdoutOS, config->emitChainedFixups = shouldEmitChainedFixups(args); config->emitInitOffsets = config->emitChainedFixups || args.hasArg(OPT_init_offsets); + config->emitRelativeMethodLists = shouldEmitRelativeMethodLists(args); config->icfLevel = getICFLevel(args); config->dedupStrings = args.hasFlag(OPT_deduplicate_strings, OPT_no_deduplicate_strings, true); diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp index 22930d52dd1d..e3d7a400e4ce 100644 --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -46,6 +46,14 @@ void lld::macho::addInputSection(InputSection *inputSection) { if (auto *isec = dyn_cast(inputSection)) { if (isec->isCoalescedWeak()) return; + if (config->emitRelativeMethodLists && + ObjCMethListSection::isMethodList(isec)) { + if (in.objcMethList->inputOrder == UnspecifiedInputOrder) + in.objcMethList->inputOrder = inputSectionsOrder++; + in.objcMethList->addInput(isec); + isec->parent = in.objcMethList; + return; + } if (config->emitInitOffsets && sectionType(isec->getFlags()) == S_MOD_INIT_FUNC_POINTERS) { in.initOffsets->addInput(isec); diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h index 694bdf734907..a0e6afef92cb 100644 --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -342,6 +342,7 @@ constexpr const char moduleTermFunc[] = "__mod_term_func"; constexpr const char nonLazySymbolPtr[] = "__nl_symbol_ptr"; constexpr const char objcCatList[] = "__objc_catlist"; constexpr const char objcClassList[] = "__objc_classlist"; +constexpr const char objcMethList[] = "__objc_methlist"; constexpr const char objcClassRefs[] = "__objc_classrefs"; constexpr const char objcConst[] = "__objc_const"; constexpr const char objCImageInfo[] = "__objc_imageinfo"; diff --git a/lld/MachO/MapFile.cpp b/lld/MachO/MapFile.cpp index f736360624eb..2a31a5c09cdd 100644 --- a/lld/MachO/MapFile.cpp +++ b/lld/MachO/MapFile.cpp @@ -197,18 +197,24 @@ void macho::writeMapFile() { seg->name.str().c_str(), osec->name.str().c_str()); } + // Shared function to print an array of symbols. + auto printIsecArrSyms = [&](const std::vector &arr) { + for (const ConcatInputSection *isec : arr) { + for (Defined *sym : isec->symbols) { + if (!(isPrivateLabel(sym->getName()) && sym->size == 0)) + os << format("0x%08llX\t0x%08llX\t[%3u] %s\n", sym->getVA(), + sym->size, readerToFileOrdinal[sym->getFile()], + sym->getName().str().data()); + } + } + }; + os << "# Symbols:\n"; os << "# Address\tSize \tFile Name\n"; for (const OutputSegment *seg : outputSegments) { for (const OutputSection *osec : seg->getSections()) { if (auto *concatOsec = dyn_cast(osec)) { - for (const InputSection *isec : concatOsec->inputs) { - for (Defined *sym : isec->symbols) - if (!(isPrivateLabel(sym->getName()) && sym->size == 0)) - os << format("0x%08llX\t0x%08llX\t[%3u] %s\n", sym->getVA(), - sym->size, readerToFileOrdinal[sym->getFile()], - sym->getName().str().data()); - } + printIsecArrSyms(concatOsec->inputs); } else if (osec == in.cStringSection || osec == in.objcMethnameSection) { const auto &liveCStrings = info.liveCStringsForSection.lookup(osec); uint64_t lastAddr = 0; // strings will never start at address 0, so this @@ -237,6 +243,8 @@ void macho::writeMapFile() { printNonLazyPointerSection(os, in.got); } else if (osec == in.tlvPointers) { printNonLazyPointerSection(os, in.tlvPointers); + } else if (osec == in.objcMethList) { + printIsecArrSyms(in.objcMethList->getInputs()); } // TODO print other synthetic sections } diff --git a/lld/MachO/ObjC.h b/lld/MachO/ObjC.h index 9fbe984e6223..8081605670c5 100644 --- a/lld/MachO/ObjC.h +++ b/lld/MachO/ObjC.h @@ -22,6 +22,8 @@ constexpr const char klassPropList[] = "__OBJC_$_CLASS_PROP_LIST_"; constexpr const char metaclass[] = "_OBJC_METACLASS_$_"; constexpr const char ehtype[] = "_OBJC_EHTYPE_$_"; constexpr const char ivar[] = "_OBJC_IVAR_$_"; +constexpr const char instanceMethods[] = "__OBJC_$_INSTANCE_METHODS_"; +constexpr const char classMethods[] = "__OBJC_$_CLASS_METHODS_"; constexpr const char listProprieties[] = "__OBJC_$_PROP_LIST_"; constexpr const char category[] = "__OBJC_$_CATEGORY_"; diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td index 0d8ee2a0926b..19f8509ba714 100644 --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -1284,6 +1284,12 @@ def fixup_chains_section : Flag<["-"], "fixup_chains_section">, HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, Group; +def objc_relative_method_lists : Flag<["-"], "objc_relative_method_lists">, + HelpText<"Emit relative method lists (more compact representation)">, + Group; +def no_objc_relative_method_lists : Flag<["-"], "no_objc_relative_method_lists">, + HelpText<"Don't emit relative method lists (use traditional representation)">, + Group; def flto_codegen_only : Flag<["-"], "flto-codegen-only">, HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 0afbbd478bb9..808ea8eac6eb 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -12,6 +12,7 @@ #include "ExportTrie.h" #include "InputFiles.h" #include "MachOStructs.h" +#include "ObjC.h" #include "OutputSegment.h" #include "SymbolTable.h" #include "Symbols.h" @@ -1975,6 +1976,241 @@ void InitOffsetsSection::setUp() { } } +ObjCMethListSection::ObjCMethListSection() + : SyntheticSection(segment_names::text, section_names::objcMethList) { + flags = S_ATTR_NO_DEAD_STRIP; + align = relativeOffsetSize; +} + +// Go through all input method lists and ensure that we have selrefs for all +// their method names. The selrefs will be needed later by ::writeTo. We need to +// create them early on here to ensure they are processed correctly by the lld +// pipeline. +void ObjCMethListSection::setUp() { + for (const ConcatInputSection *isec : inputs) { + uint32_t structSizeAndFlags = 0, structCount = 0; + readMethodListHeader(isec->data.data(), structSizeAndFlags, structCount); + uint32_t originalStructSize = structSizeAndFlags & structSizeMask; + // Method name is immediately after header + uint32_t methodNameOff = methodListHeaderSize; + + // Loop through all methods, and ensure a selref for each of them exists. + while (methodNameOff < isec->data.size()) { + const Reloc *reloc = isec->getRelocAt(methodNameOff); + assert(reloc && "Relocation expected at method list name slot"); + auto *def = dyn_cast_or_null(reloc->referent.get()); + assert(def && "Expected valid Defined at method list name slot"); + auto *cisec = cast(def->isec); + assert(cisec && "Expected method name to be in a CStringInputSection"); + auto methname = cisec->getStringRefAtOffset(def->value); + if (!ObjCSelRefsHelper::getSelRef(methname)) + ObjCSelRefsHelper::makeSelRef(methname); + + // Jump to method name offset in next struct + methodNameOff += originalStructSize; + } + } +} + +// Calculate section size and final offsets for where InputSection's need to be +// written. +void ObjCMethListSection::finalize() { + // sectionSize will be the total size of the __objc_methlist section + sectionSize = 0; + for (ConcatInputSection *isec : inputs) { + // We can also use sectionSize as write offset for isec + assert(sectionSize == alignToPowerOf2(sectionSize, relativeOffsetSize) && + "expected __objc_methlist to be aligned by default with the " + "required section alignment"); + isec->outSecOff = sectionSize; + + isec->isFinal = true; + uint32_t relativeListSize = + computeRelativeMethodListSize(isec->data.size()); + sectionSize += relativeListSize; + + // If encoding the method list in relative offset format shrinks the size, + // then we also need to adjust symbol sizes to match the new size. Note that + // on 32bit platforms the size of the method list will remain the same when + // encoded in relative offset format. + if (relativeListSize != isec->data.size()) { + for (Symbol *sym : isec->symbols) { + assert(isa(sym) && + "Unexpected undefined symbol in ObjC method list"); + auto *def = cast(sym); + // There can be 0-size symbols, check if this is the case and ignore + // them. + if (def->size) { + assert( + def->size == isec->data.size() && + "Invalid ObjC method list symbol size: expected symbol size to " + "match isec size"); + def->size = relativeListSize; + } + } + } + } +} + +void ObjCMethListSection::writeTo(uint8_t *bufStart) const { + uint8_t *buf = bufStart; + for (const ConcatInputSection *isec : inputs) { + assert(buf - bufStart == long(isec->outSecOff) && + "Writing at unexpected offset"); + uint32_t writtenSize = writeRelativeMethodList(isec, buf); + buf += writtenSize; + } + assert(buf - bufStart == sectionSize && + "Written size does not match expected section size"); +} + +// Check if an InputSection is a method list. To do this we scan the +// InputSection for any symbols who's names match the patterns we expect clang +// to generate for method lists. +bool ObjCMethListSection::isMethodList(const ConcatInputSection *isec) { + const char *symPrefixes[] = {objc::symbol_names::classMethods, + objc::symbol_names::instanceMethods, + objc::symbol_names::categoryInstanceMethods, + objc::symbol_names::categoryClassMethods}; + if (!isec) + return false; + for (const Symbol *sym : isec->symbols) { + auto *def = dyn_cast_or_null(sym); + if (!def) + continue; + for (const char *prefix : symPrefixes) { + if (def->getName().starts_with(prefix)) { + assert(def->size == isec->data.size() && + "Invalid ObjC method list symbol size: expected symbol size to " + "match isec size"); + assert(def->value == 0 && + "Offset of ObjC method list symbol must be 0"); + return true; + } + } + } + + return false; +} + +// Encode a single relative offset value. The input is the data/symbol at +// (&isec->data[inSecOff]). The output is written to (&buf[outSecOff]). +// 'createSelRef' indicates that we should not directly use the specified +// symbol, but instead get the selRef for the symbol and use that instead. +void ObjCMethListSection::writeRelativeOffsetForIsec( + const ConcatInputSection *isec, uint8_t *buf, uint32_t &inSecOff, + uint32_t &outSecOff, bool useSelRef) const { + const Reloc *reloc = isec->getRelocAt(inSecOff); + assert(reloc && "Relocation expected at __objc_methlist Offset"); + auto *def = dyn_cast_or_null(reloc->referent.get()); + assert(def && "Expected all syms in __objc_methlist to be defined"); + uint32_t symVA = def->getVA(); + + if (useSelRef) { + auto *cisec = cast(def->isec); + auto methname = cisec->getStringRefAtOffset(def->value); + ConcatInputSection *selRef = ObjCSelRefsHelper::getSelRef(methname); + assert(selRef && "Expected all selector names to already be already be " + "present in __objc_selrefs"); + symVA = selRef->getVA(); + assert(selRef->data.size() == sizeof(target->wordSize) && + "Expected one selref per ConcatInputSection"); + } + + uint32_t currentVA = isec->getVA() + outSecOff; + uint32_t delta = symVA - currentVA; + write32le(buf + outSecOff, delta); + + // Move one pointer forward in the absolute method list + inSecOff += target->wordSize; + // Move one relative offset forward in the relative method list (32 bits) + outSecOff += relativeOffsetSize; +} + +// Write a relative method list to buf, return the size of the written +// information +uint32_t +ObjCMethListSection::writeRelativeMethodList(const ConcatInputSection *isec, + uint8_t *buf) const { + // Copy over the header, and add the "this is a relative method list" magic + // value flag + uint32_t structSizeAndFlags = 0, structCount = 0; + readMethodListHeader(isec->data.data(), structSizeAndFlags, structCount); + // Set the struct size for the relative method list + uint32_t relativeStructSizeAndFlags = + (relativeOffsetSize * pointersPerStruct) & structSizeMask; + // Carry over the old flags from the input struct + relativeStructSizeAndFlags |= structSizeAndFlags & structFlagsMask; + // Set the relative method list flag + relativeStructSizeAndFlags |= relMethodHeaderFlag; + + writeMethodListHeader(buf, relativeStructSizeAndFlags, structCount); + + assert(methodListHeaderSize + + (structCount * pointersPerStruct * target->wordSize) == + isec->data.size() && + "Invalid computed ObjC method list size"); + + uint32_t inSecOff = methodListHeaderSize; + uint32_t outSecOff = methodListHeaderSize; + + // Go through the method list and encode input absolute pointers as relative + // offsets. writeRelativeOffsetForIsec will be incrementing inSecOff and + // outSecOff + for (uint32_t i = 0; i < structCount; i++) { + // Write the name of the method + writeRelativeOffsetForIsec(isec, buf, inSecOff, outSecOff, true); + // Write the type of the method + writeRelativeOffsetForIsec(isec, buf, inSecOff, outSecOff, false); + // Write reference to the selector of the method + writeRelativeOffsetForIsec(isec, buf, inSecOff, outSecOff, false); + } + + // Expecting to have read all the data in the isec + assert(inSecOff == isec->data.size() && + "Invalid actual ObjC method list size"); + assert( + outSecOff == computeRelativeMethodListSize(inSecOff) && + "Mismatch between input & output size when writing relative method list"); + return outSecOff; +} + +// Given the size of an ObjC method list InputSection, return the size of the +// method list when encoded in relative offsets format. We can do this without +// decoding the actual data, as it can be directly inferred from the size of the +// isec. +uint32_t ObjCMethListSection::computeRelativeMethodListSize( + uint32_t absoluteMethodListSize) const { + uint32_t oldPointersSize = absoluteMethodListSize - methodListHeaderSize; + uint32_t pointerCount = oldPointersSize / target->wordSize; + assert(((pointerCount % pointersPerStruct) == 0) && + "__objc_methlist expects method lists to have multiple-of-3 pointers"); + + uint32_t newPointersSize = pointerCount * relativeOffsetSize; + uint32_t newTotalSize = methodListHeaderSize + newPointersSize; + + assert((newTotalSize <= absoluteMethodListSize) && + "Expected relative method list size to be smaller or equal than " + "original size"); + return newTotalSize; +} + +// Read a method list header from buf +void ObjCMethListSection::readMethodListHeader(const uint8_t *buf, + uint32_t &structSizeAndFlags, + uint32_t &structCount) const { + structSizeAndFlags = read32le(buf); + structCount = read32le(buf + sizeof(uint32_t)); +} + +// Write a method list header to buf +void ObjCMethListSection::writeMethodListHeader(uint8_t *buf, + uint32_t structSizeAndFlags, + uint32_t structCount) const { + write32le(buf, structSizeAndFlags); + write32le(buf + sizeof(structSizeAndFlags), structCount); +} + void macho::createSyntheticSymbols() { auto addHeaderSymbol = [](const char *name) { symtab->addSynthetic(name, in.header->isec, /*value=*/0, diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h index 4586a4a0bf43..e8fadfef56d4 100644 --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -684,6 +684,54 @@ private: std::vector sections; }; +// This SyntheticSection is for the __objc_methlist section, which contains +// relative method lists if the -objc_relative_method_lists option is enabled. +class ObjCMethListSection final : public SyntheticSection { +public: + ObjCMethListSection(); + + static bool isMethodList(const ConcatInputSection *isec); + void addInput(ConcatInputSection *isec) { inputs.push_back(isec); } + std::vector getInputs() { return inputs; } + + void setUp(); + void finalize() override; + bool isNeeded() const override { return !inputs.empty(); } + uint64_t getSize() const override { return sectionSize; } + void writeTo(uint8_t *bufStart) const override; + +private: + void readMethodListHeader(const uint8_t *buf, uint32_t &structSizeAndFlags, + uint32_t &structCount) const; + void writeMethodListHeader(uint8_t *buf, uint32_t structSizeAndFlags, + uint32_t structCount) const; + uint32_t computeRelativeMethodListSize(uint32_t absoluteMethodListSize) const; + void writeRelativeOffsetForIsec(const ConcatInputSection *isec, uint8_t *buf, + uint32_t &inSecOff, uint32_t &outSecOff, + bool useSelRef) const; + uint32_t writeRelativeMethodList(const ConcatInputSection *isec, + uint8_t *buf) const; + + static constexpr uint32_t methodListHeaderSize = + /*structSizeAndFlags*/ sizeof(uint32_t) + + /*structCount*/ sizeof(uint32_t); + // Relative method lists are supported only for 3-pointer method lists + static constexpr uint32_t pointersPerStruct = 3; + // The runtime identifies relative method lists via this magic value + static constexpr uint32_t relMethodHeaderFlag = 0x80000000; + // In the method list header, the first 2 bytes are the size of struct + static constexpr uint32_t structSizeMask = 0x0000FFFF; + // In the method list header, the last 2 bytes are the flags for the struct + static constexpr uint32_t structFlagsMask = 0xFFFF0000; + // Relative method lists have 4 byte alignment as all data in the InputSection + // is 4 byte + static constexpr uint32_t relativeOffsetSize = sizeof(uint32_t); + + // The output size of the __objc_methlist section, computed during finalize() + uint32_t sectionSize = 0; + std::vector inputs; +}; + // Chained fixups are a replacement for classic dyld opcodes. In this format, // most of the metadata necessary for binding symbols and rebasing addresses is // stored directly in the memory location that will have the fixup applied. @@ -810,6 +858,7 @@ struct InStruct { ObjCImageInfoSection *objCImageInfo = nullptr; ConcatInputSection *imageLoaderCache = nullptr; InitOffsetsSection *initOffsets = nullptr; + ObjCMethListSection *objcMethList = nullptr; ChainedFixupsSection *chainedFixups = nullptr; }; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index a18b5268fd42..fe989de648d7 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -1292,6 +1292,8 @@ template void Writer::run() { scanSymbols(); if (in.objcStubs->isNeeded()) in.objcStubs->setUp(); + if (in.objcMethList->isNeeded()) + in.objcMethList->setUp(); scanRelocations(); if (in.initOffsets->isNeeded()) in.initOffsets->setUp(); @@ -1363,6 +1365,7 @@ void macho::createSyntheticSections() { in.unwindInfo = makeUnwindInfoSection(); in.objCImageInfo = make(); in.initOffsets = make(); + in.objcMethList = make(); // This section contains space for just a single word, and will be used by // dyld to cache an address to the image loader it uses. diff --git a/lld/test/MachO/objc-relative-method-lists-simple.s b/lld/test/MachO/objc-relative-method-lists-simple.s new file mode 100644 index 000000000000..1ffec3c6241c --- /dev/null +++ b/lld/test/MachO/objc-relative-method-lists-simple.s @@ -0,0 +1,245 @@ +# REQUIRES: aarch64 +# RUN: rm -rf %t; split-file %s %t && cd %t + +## Compile a64_rel_dylib.o +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_rel_dylib.o a64_simple_class.s + +## Test arm64 + relative method lists +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL + +## Test arm64 + traditional method lists (no relative offsets) +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -no_objc_relative_method_lists +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_NO_REL + + +CHK_REL: Contents of (__DATA_CONST,__objc_classlist) section +CHK_REL-NEXT: _OBJC_CLASS_$_MyClass +CHK_REL: baseMethods +CHK_REL-NEXT: entsize 12 (relative) +CHK_REL-NEXT: count 3 +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_00 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_00] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_01 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_01] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_02 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_02] + +CHK_REL: Meta Class +CHK_REL-NEXT: isa 0x{{[0-9a-f]*}} _OBJC_METACLASS_$_MyClass +CHK_REL: baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *) +CHK_REL-NEXT: entsize 12 (relative) +CHK_REL-NEXT: count 3 +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) class_method_00 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) +[MyClass class_method_00] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) class_method_01 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) +[MyClass class_method_01] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) class_method_02 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) +[MyClass class_method_02] + + +CHK_NO_REL-NOT: (relative) + +CHK_NO_REL: Contents of (__DATA_CONST,__objc_classlist) section +CHK_NO_REL-NEXT: _OBJC_CLASS_$_MyClass + +CHK_NO_REL: baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *) +CHK_NO_REL-NEXT: entsize 24 +CHK_NO_REL-NEXT: count 3 +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} instance_method_00 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp -[MyClass instance_method_00] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} instance_method_01 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp -[MyClass instance_method_01] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} instance_method_02 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp -[MyClass instance_method_02] + + +CHK_NO_REL: Meta Class +CHK_NO_REL-NEXT: _OBJC_METACLASS_$_MyClass + +CHK_NO_REL: baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *) +CHK_NO_REL-NEXT: entsize 24 +CHK_NO_REL-NEXT: count 3 +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} class_method_00 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp +[MyClass class_method_00] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} class_method_01 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp +[MyClass class_method_01] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} class_method_02 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp +[MyClass class_method_02] + + +######################## Generate a64_simple_class.s ######################### +# clang -c simple_class.mm -s -o a64_simple_class.s -target arm64-apple-macos -arch arm64 -Oz + +######################## simple_class.mm ######################## +# __attribute__((objc_root_class)) +# @interface MyClass +# - (void)instance_method_00; +# - (void)instance_method_01; +# - (void)instance_method_02; +# + (void)class_method_00; +# + (void)class_method_01; +# + (void)class_method_02; +# @end +# +# @implementation MyClass +# - (void)instance_method_00 {} +# - (void)instance_method_01 {} +# - (void)instance_method_02 {} +# + (void)class_method_00 {} +# + (void)class_method_01 {} +# + (void)class_method_02 {} +# @end +# +# void *_objc_empty_cache; +# void *_objc_empty_vtable; +# + +#--- objc-macros.s +.macro .objc_selector_def name + .p2align 2 +"\name": + .cfi_startproc + ret + .cfi_endproc +.endm + +#--- a64_simple_class.s +.include "objc-macros.s" + +.section __TEXT,__text,regular,pure_instructions +.build_version macos, 11, 0 + +.objc_selector_def "-[MyClass instance_method_00]" +.objc_selector_def "-[MyClass instance_method_01]" +.objc_selector_def "-[MyClass instance_method_02]" + +.objc_selector_def "+[MyClass class_method_00]" +.objc_selector_def "+[MyClass class_method_01]" +.objc_selector_def "+[MyClass class_method_02]" + +.globl __objc_empty_vtable +.zerofill __DATA,__common,__objc_empty_vtable,8,3 +.section __DATA,__objc_data +.globl _OBJC_CLASS_$_MyClass +.p2align 3, 0x0 + +_OBJC_CLASS_$_MyClass: + .quad _OBJC_METACLASS_$_MyClass + .quad 0 + .quad __objc_empty_cache + .quad __objc_empty_vtable + .quad __OBJC_CLASS_RO_$_MyClass + .globl _OBJC_METACLASS_$_MyClass + .p2align 3, 0x0 + +_OBJC_METACLASS_$_MyClass: + .quad _OBJC_METACLASS_$_MyClass + .quad _OBJC_CLASS_$_MyClass + .quad __objc_empty_cache + .quad __objc_empty_vtable + .quad __OBJC_METACLASS_RO_$_MyClass + + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_: + .asciz "MyClass" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_: + .asciz "class_method_00" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_: + .asciz "v16@0:8" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.1: + .asciz "class_method_01" +l_OBJC_METH_VAR_NAME_.2: + .asciz "class_method_02" + .section __DATA,__objc_const + .p2align 3, 0x0 +__OBJC_$_CLASS_METHODS_MyClass: + .long 24 + .long 3 + .quad l_OBJC_METH_VAR_NAME_ + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyClass class_method_00]" + .quad l_OBJC_METH_VAR_NAME_.1 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyClass class_method_01]" + .quad l_OBJC_METH_VAR_NAME_.2 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyClass class_method_02]" + .p2align 3, 0x0 + +__OBJC_METACLASS_RO_$_MyClass: + .long 3 + .long 40 + .long 40 + .space 4 + .quad 0 + .quad l_OBJC_CLASS_NAME_ + .quad __OBJC_$_CLASS_METHODS_MyClass + .quad 0 + .quad 0 + .quad 0 + .quad 0 + + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.3: + .asciz "instance_method_00" +l_OBJC_METH_VAR_NAME_.4: + .asciz "instance_method_01" +l_OBJC_METH_VAR_NAME_.5: + .asciz "instance_method_02" + + .section __DATA,__objc_const + .p2align 3, 0x0 +__OBJC_$_INSTANCE_METHODS_MyClass: + .long 24 + .long 3 + .quad l_OBJC_METH_VAR_NAME_.3 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyClass instance_method_00]" + .quad l_OBJC_METH_VAR_NAME_.4 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyClass instance_method_01]" + .quad l_OBJC_METH_VAR_NAME_.5 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyClass instance_method_02]" + .p2align 3, 0x0 + +__OBJC_CLASS_RO_$_MyClass: + .long 2 + .long 0 + .long 0 + .space 4 + .quad 0 + .quad l_OBJC_CLASS_NAME_ + .quad __OBJC_$_INSTANCE_METHODS_MyClass + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .globl __objc_empty_cache + +.zerofill __DATA,__common,__objc_empty_cache,8,3 + .section __DATA,__objc_classlist,regular,no_dead_strip + .p2align 3, 0x0 +l_OBJC_LABEL_CLASS_$: + .quad _OBJC_CLASS_$_MyClass + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 64 +.subsections_via_symbols -- GitLab From d94dc5f0d63be3d786224f57c061ef16687fca9a Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 27 Mar 2024 14:32:13 -0700 Subject: [PATCH 127/541] [SLP]Fix PR86763: do not truncate reductions to the demanded bits size. Need to adjust ReductionBitWIdth after minbitwidth analysis, if the demanded bits analysis sjows tht its size is less than the size of the vectorized value. It prevents incorrect sign-zero extension transformation after. --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 7 +++++++ .../RISCV/reduction-extension-after-bitwidth.ll | 4 ++-- .../SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll | 5 ++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index e1f26b922dbe..7f528848002b 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -14415,6 +14415,13 @@ void BoUpSLP::computeMinimumValueSizes() { unsigned MaxBitWidth = ComputeMaxBitWidth( TreeRoot, VectorizableTree[NodeIdx]->getVectorFactor(), IsTopRoot, IsProfitableToDemoteRoot, Opcode, Limit, IsTruncRoot); + if (ReductionBitWidth != 0 && (IsTopRoot || !RootDemotes.empty())) { + if (MaxBitWidth != 0 && ReductionBitWidth < MaxBitWidth) + ReductionBitWidth = bit_ceil(MaxBitWidth); + else if (MaxBitWidth == 0) + ReductionBitWidth = 0; + } + for (unsigned Idx : RootDemotes) ToDemote.append(VectorizableTree[Idx]->Scalars.begin(), VectorizableTree[Idx]->Scalars.end()); diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll index 611003a55d73..7771e8369b61 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll @@ -6,8 +6,8 @@ define i32 @test(ptr %0, ptr %1) { ; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LOAD_5:%.*]] = load i32, ptr [[TMP1]], align 4 -; CHECK-NEXT: [[TMP2:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> ) -; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[TMP2]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.vector.reduce.and.v4i8(<4 x i8> ) +; CHECK-NEXT: [[TMP3:%.*]] = sext i8 [[TMP2]] to i32 ; CHECK-NEXT: [[OP_RDX:%.*]] = and i32 [[TMP3]], [[LOAD_5]] ; CHECK-NEXT: ret i32 [[OP_RDX]] ; diff --git a/llvm/test/Transforms/SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll b/llvm/test/Transforms/SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll index cfe3ca9f8f9e..7b4e2b0ce911 100644 --- a/llvm/test/Transforms/SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll +++ b/llvm/test/Transforms/SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll @@ -11,9 +11,8 @@ define void @test(ptr %a, i8 %0, i16 %b.promoted.i) { ; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i128> [[TMP5]], <4 x i128> poison, <4 x i32> zeroinitializer ; CHECK-NEXT: [[TMP7:%.*]] = trunc <4 x i128> [[TMP6]] to <4 x i16> ; CHECK-NEXT: [[TMP8:%.*]] = or <4 x i16> [[TMP4]], [[TMP7]] -; CHECK-NEXT: [[TMP9:%.*]] = trunc <4 x i16> [[TMP8]] to <4 x i1> -; CHECK-NEXT: [[TMP10:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP9]]) -; CHECK-NEXT: [[TMP11:%.*]] = zext i1 [[TMP10]] to i64 +; CHECK-NEXT: [[TMP9:%.*]] = call i16 @llvm.vector.reduce.and.v4i16(<4 x i16> [[TMP8]]) +; CHECK-NEXT: [[TMP11:%.*]] = zext i16 [[TMP9]] to i64 ; CHECK-NEXT: [[OP_RDX:%.*]] = and i64 [[TMP11]], 1 ; CHECK-NEXT: store i64 [[OP_RDX]], ptr [[A]], align 8 ; CHECK-NEXT: ret void -- GitLab From 0a43ca731b1faedd885f86153ecc570dde602ca3 Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Wed, 27 Mar 2024 17:40:58 -0400 Subject: [PATCH 128/541] [AMDGPU] Fix missing `IsExact` flag when expanding vector binary operator (#86712) --- .../Target/AMDGPU/AMDGPUCodeGenPrepare.cpp | 3 + .../AMDGPU/amdgpu-codegenprepare-idiv.ll | 108 ++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp index bddf3d958a1a..6e7d34f5adaa 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp @@ -1594,6 +1594,9 @@ bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &I) { } } + if (auto *NewEltI = dyn_cast(NewElt)) + NewEltI->copyIRFlags(&I); + NewDiv = Builder.CreateInsertElement(NewDiv, NewElt, N); } } else { diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll index d9001656f308..2ad28b8dd6ec 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll @@ -10668,3 +10668,111 @@ define amdgpu_kernel void @srem_v2i64_pow2_shl_denom(ptr addrspace(1) %out, <2 x store <2 x i64> %r, ptr addrspace(1) %out ret void } + +define <2 x i32> @v_sdiv_i32_exact(<2 x i32> %num) { +; CHECK-LABEL: @v_sdiv_i32_exact( +; CHECK: %1 = extractelement <2 x i32> %num, i64 0 +; CHECK-NEXT: %2 = sdiv exact i32 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i32> poison, i32 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i32> %num, i64 1 +; CHECK-NEXT: %5 = sdiv exact i32 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i32> %3, i32 %5, i64 1 +; CHECK-NEXT: ret <2 x i32> %6 +; +; GFX6-LABEL: v_sdiv_i32_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_ashrrev_i32_e32 v0, 12, v0 +; GFX6-NEXT: v_ashrrev_i32_e32 v1, 10, v1 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_sdiv_i32_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_ashrrev_i32_e32 v0, 12, v0 +; GFX9-NEXT: v_ashrrev_i32_e32 v1, 10, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact <2 x i32> %num, + ret <2 x i32> %result +} + +define <2 x i64> @v_sdiv_i64_exact(<2 x i64> %num) { +; CHECK-LABEL: @v_sdiv_i64_exact( +; CHECK: %1 = extractelement <2 x i64> %num, i64 0 +; CHECK-NEXT: %2 = sdiv exact i64 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i64> poison, i64 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i64> %num, i64 1 +; CHECK-NEXT: %5 = sdiv exact i64 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i64> %3, i64 %5, i64 1 +; CHECK-NEXT: ret <2 x i64> %6 +; +; GFX6-LABEL: v_sdiv_i64_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_ashr_i64 v[0:1], v[0:1], 12 +; GFX6-NEXT: v_ashr_i64 v[2:3], v[2:3], 10 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_sdiv_i64_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_ashrrev_i64 v[0:1], 12, v[0:1] +; GFX9-NEXT: v_ashrrev_i64 v[2:3], 10, v[2:3] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact <2 x i64> %num, + ret <2 x i64> %result +} + +define <2 x i32> @v_udiv_i32_exact(<2 x i32> %num) { +; CHECK-LABEL: @v_udiv_i32_exact( +; CHECK: %1 = extractelement <2 x i32> %num, i64 0 +; CHECK-NEXT: %2 = udiv exact i32 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i32> poison, i32 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i32> %num, i64 1 +; CHECK-NEXT: %5 = udiv exact i32 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i32> %3, i32 %5, i64 1 +; CHECK-NEXT: ret <2 x i32> %6 +; +; GFX6-LABEL: v_udiv_i32_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_lshrrev_b32_e32 v0, 12, v0 +; GFX6-NEXT: v_lshrrev_b32_e32 v1, 10, v1 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_udiv_i32_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_lshrrev_b32_e32 v0, 12, v0 +; GFX9-NEXT: v_lshrrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = udiv exact <2 x i32> %num, + ret <2 x i32> %result +} + +define <2 x i64> @v_udiv_i64_exact(<2 x i64> %num) { +; CHECK-LABEL: @v_udiv_i64_exact( +; CHECK: %1 = extractelement <2 x i64> %num, i64 0 +; CHECK-NEXT: %2 = udiv exact i64 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i64> poison, i64 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i64> %num, i64 1 +; CHECK-NEXT: %5 = udiv exact i64 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i64> %3, i64 %5, i64 1 +; CHECK-NEXT: ret <2 x i64> %6 +; +; GFX6-LABEL: v_udiv_i64_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_lshr_b64 v[0:1], v[0:1], 12 +; GFX6-NEXT: v_lshr_b64 v[2:3], v[2:3], 10 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_udiv_i64_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_lshrrev_b64 v[0:1], 12, v[0:1] +; GFX9-NEXT: v_lshrrev_b64 v[2:3], 10, v[2:3] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = udiv exact <2 x i64> %num, + ret <2 x i64> %result +} -- GitLab From a8b90c047d5bb47702eebd4ceeb763e8537981a1 Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Wed, 27 Mar 2024 17:41:30 -0400 Subject: [PATCH 129/541] [GlobalISel] Update `MachineIRBuilder::buildAtomicRMW` interface (#86851) --- .../CodeGen/GlobalISel/MachineIRBuilder.h | 11 ++-- .../CodeGen/GlobalISel/MachineIRBuilder.cpp | 54 ++++++++++--------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 16a7fc446fbe..4c9d85fd9f51 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1333,9 +1333,9 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder - buildAtomicCmpXchgWithSuccess(Register OldValRes, Register SuccessRes, - Register Addr, Register CmpVal, Register NewVal, - MachineMemOperand &MMO); + buildAtomicCmpXchgWithSuccess(const DstOp &OldValRes, const DstOp &SuccessRes, + const SrcOp &Addr, const SrcOp &CmpVal, + const SrcOp &NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, /// MMO`. @@ -1351,8 +1351,9 @@ public: /// registers of the same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicCmpXchg(Register OldValRes, Register Addr, - Register CmpVal, Register NewVal, + MachineInstrBuilder buildAtomicCmpXchg(const DstOp &OldValRes, + const SrcOp &Addr, const SrcOp &CmpVal, + const SrcOp &NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes = G_ATOMICRMW_ Addr, Val, MMO`. diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 07d4cb5eaa23..b8ba782254c3 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -930,14 +930,14 @@ MachineIRBuilder::buildExtractVectorElement(const DstOp &Res, const SrcOp &Val, } MachineInstrBuilder MachineIRBuilder::buildAtomicCmpXchgWithSuccess( - Register OldValRes, Register SuccessRes, Register Addr, Register CmpVal, - Register NewVal, MachineMemOperand &MMO) { + const DstOp &OldValRes, const DstOp &SuccessRes, const SrcOp &Addr, + const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) { #ifndef NDEBUG - LLT OldValResTy = getMRI()->getType(OldValRes); - LLT SuccessResTy = getMRI()->getType(SuccessRes); - LLT AddrTy = getMRI()->getType(Addr); - LLT CmpValTy = getMRI()->getType(CmpVal); - LLT NewValTy = getMRI()->getType(NewVal); + LLT OldValResTy = OldValRes.getLLTTy(*getMRI()); + LLT SuccessResTy = SuccessRes.getLLTTy(*getMRI()); + LLT AddrTy = Addr.getLLTTy(*getMRI()); + LLT CmpValTy = CmpVal.getLLTTy(*getMRI()); + LLT NewValTy = NewVal.getLLTTy(*getMRI()); assert(OldValResTy.isScalar() && "invalid operand type"); assert(SuccessResTy.isScalar() && "invalid operand type"); assert(AddrTy.isPointer() && "invalid operand type"); @@ -947,24 +947,25 @@ MachineInstrBuilder MachineIRBuilder::buildAtomicCmpXchgWithSuccess( assert(OldValResTy == NewValTy && "type mismatch"); #endif - return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) - .addDef(OldValRes) - .addDef(SuccessRes) - .addUse(Addr) - .addUse(CmpVal) - .addUse(NewVal) - .addMemOperand(&MMO); + auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS); + OldValRes.addDefToMIB(*getMRI(), MIB); + SuccessRes.addDefToMIB(*getMRI(), MIB); + Addr.addSrcToMIB(MIB); + CmpVal.addSrcToMIB(MIB); + NewVal.addSrcToMIB(MIB); + MIB.addMemOperand(&MMO); + return MIB; } MachineInstrBuilder -MachineIRBuilder::buildAtomicCmpXchg(Register OldValRes, Register Addr, - Register CmpVal, Register NewVal, +MachineIRBuilder::buildAtomicCmpXchg(const DstOp &OldValRes, const SrcOp &Addr, + const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) { #ifndef NDEBUG - LLT OldValResTy = getMRI()->getType(OldValRes); - LLT AddrTy = getMRI()->getType(Addr); - LLT CmpValTy = getMRI()->getType(CmpVal); - LLT NewValTy = getMRI()->getType(NewVal); + LLT OldValResTy = OldValRes.getLLTTy(*getMRI()); + LLT AddrTy = Addr.getLLTTy(*getMRI()); + LLT CmpValTy = CmpVal.getLLTTy(*getMRI()); + LLT NewValTy = NewVal.getLLTTy(*getMRI()); assert(OldValResTy.isScalar() && "invalid operand type"); assert(AddrTy.isPointer() && "invalid operand type"); assert(CmpValTy.isValid() && "invalid operand type"); @@ -973,12 +974,13 @@ MachineIRBuilder::buildAtomicCmpXchg(Register OldValRes, Register Addr, assert(OldValResTy == NewValTy && "type mismatch"); #endif - return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG) - .addDef(OldValRes) - .addUse(Addr) - .addUse(CmpVal) - .addUse(NewVal) - .addMemOperand(&MMO); + auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG); + OldValRes.addDefToMIB(*getMRI(), MIB); + Addr.addSrcToMIB(MIB); + CmpVal.addSrcToMIB(MIB); + NewVal.addSrcToMIB(MIB); + MIB.addMemOperand(&MMO); + return MIB; } MachineInstrBuilder MachineIRBuilder::buildAtomicRMW( -- GitLab From 5da39372e39f3aebf63e07faf774b6ed37cad3fb Mon Sep 17 00:00:00 2001 From: smanna12 Date: Wed, 27 Mar 2024 16:44:41 -0500 Subject: [PATCH 130/541] [clang-installapi] Remove unnecessary copy (#86808) Reported by Static Analyzer Tool: In clang::installapi::InstallAPIVisitor::VisitFunctionDecl(clang::FunctionDecl const *): Using the auto keyword without an & causes the copy of an object of type DynTypedNode. --- clang/lib/InstallAPI/Visitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index f8f5d8d53d56..6476c5107cb5 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -255,7 +255,7 @@ bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) { return true; // Skip methods in CXX RecordDecls. - for (auto P : D->getASTContext().getParents(*M)) { + for (const DynTypedNode &P : D->getASTContext().getParents(*M)) { if (P.get()) return true; } -- GitLab From b7a4ace72edf79f8250df2b08f0c14177d346770 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 27 Mar 2024 14:40:45 -0700 Subject: [PATCH 131/541] [SLP][NFC]Improve compile time by size analysis limit and reduction size limit. Used RecursionMaxDepth to limit number of lookups in BoUpSLP::getVectorElementSize and limited reduction width for bool reduced values. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 7f528848002b..961380ce4ad9 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -13928,26 +13928,29 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // that feed it. The type of the loaded value may indicate a more suitable // width than V's type. We want to base the vector element size on the width // of memory operations where possible. - SmallVector, 16> Worklist; + SmallVector> Worklist; SmallPtrSet Visited; if (auto *I = dyn_cast(V)) { - Worklist.emplace_back(I, I->getParent()); + Worklist.emplace_back(I, I->getParent(), 0); Visited.insert(I); } // Traverse the expression tree in bottom-up order looking for loads. If we // encounter an instruction we don't yet handle, we give up. auto Width = 0u; + Value *FirstNonBool = nullptr; while (!Worklist.empty()) { - Instruction *I; - BasicBlock *Parent; - std::tie(I, Parent) = Worklist.pop_back_val(); + auto [I, Parent, Level] = Worklist.pop_back_val(); // We should only be looking at scalar instructions here. If the current // instruction has a vector type, skip. auto *Ty = I->getType(); if (isa(Ty)) continue; + if (Ty != Builder.getInt1Ty() && !FirstNonBool) + FirstNonBool = I; + if (Level > RecursionMaxDepth) + continue; // If the current instruction is a load, update MaxWidth to reflect the // width of the loaded value. @@ -13960,11 +13963,16 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // user or the use is a PHI node, we add it to the worklist. else if (isa(I)) { - for (Use &U : I->operands()) + for (Use &U : I->operands()) { if (auto *J = dyn_cast(U.get())) if (Visited.insert(J).second && - (isa(I) || J->getParent() == Parent)) - Worklist.emplace_back(J, J->getParent()); + (isa(I) || J->getParent() == Parent)) { + Worklist.emplace_back(J, J->getParent(), Level + 1); + continue; + } + if (!FirstNonBool && U.get()->getType() != Builder.getInt1Ty()) + FirstNonBool = U.get(); + } } else { break; } @@ -13974,8 +13982,8 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // gave up for some reason, just return the width of V. Otherwise, return the // maximum width we found. if (!Width) { - if (auto *CI = dyn_cast(V)) - V = CI->getOperand(0); + if (V->getType() == Builder.getInt1Ty() && FirstNonBool) + V = FirstNonBool; Width = DL->getTypeSizeInBits(V->getType()); } @@ -15838,7 +15846,9 @@ public: RegMaxNumber * llvm::bit_floor(MaxVecRegSize / EltSize); unsigned ReduxWidth = std::min( - llvm::bit_floor(NumReducedVals), std::max(RedValsMaxNumber, MaxElts)); + llvm::bit_floor(NumReducedVals), + std::clamp(MaxElts, RedValsMaxNumber, + RegMaxNumber * RedValsMaxNumber)); unsigned Start = 0; unsigned Pos = Start; // Restarts vectorization attempt with lower vector factor. -- GitLab From 88812819022ecff392dfc8d3f964899f63bdffdb Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Wed, 27 Mar 2024 14:45:20 -0700 Subject: [PATCH 132/541] [RISCV] Add test coverage for (add (shl Z, c1), Y, (shl Z, c2)) variants Basically, testing for interaction of shNadd matching with one step of reassociation in the add. --- llvm/test/CodeGen/RISCV/rv64zba.ll | 90 ++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index f810f51f6bc0..d9d83633a853 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -1282,6 +1282,96 @@ define zeroext i32 @sext_ashr_zext_i8(i8 %a) nounwind { ret i32 %1 } +define i64 @sh6_sh3_add1(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add1: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add1: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: sh3add a1, a1, a2 +; RV64ZBA-NEXT: sh3add a0, a1, a0 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %shl1, %shl + %add2 = add nsw i64 %add, %x + ret i64 %add2 +} + +define i64 @sh6_sh3_add2(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add2: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: add a0, a0, a2 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add2: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: slli a1, a1, 6 +; RV64ZBA-NEXT: add a0, a1, a0 +; RV64ZBA-NEXT: sh3add a0, a2, a0 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %shl1, %x + %add2 = add nsw i64 %add, %shl + ret i64 %add2 +} + +define i64 @sh6_sh3_add3(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add3: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add3: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: sh3add a1, a1, a2 +; RV64ZBA-NEXT: sh3add a0, a1, a0 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %shl1, %shl + %add2 = add nsw i64 %x, %add + ret i64 %add2 +} + +define i64 @sh6_sh3_add4(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add4: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a0, a0, a2 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add4: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: slli a1, a1, 6 +; RV64ZBA-NEXT: sh3add a0, a2, a0 +; RV64ZBA-NEXT: add a0, a0, a1 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %x, %shl + %add2 = add nsw i64 %add, %shl1 + ret i64 %add2 +} + ; Make sure we use sext.h+slli+srli for Zba+Zbb. ; FIXME: The RV64I and Zba only cases can be done with only 3 shifts. define zeroext i32 @sext_ashr_zext_i16(i16 %a) nounwind { -- GitLab From d5f06342a3007f414c783ba42cb49453a9cee835 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Wed, 27 Mar 2024 15:09:57 -0700 Subject: [PATCH 133/541] [libc] add flag for FP_*LOGB0/NAN values (#86723) These values vary by system, this flag allows you to toggle their value. --- libc/include/llvm-libc-macros/math-macros.h | 9 +++++++-- utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libc/include/llvm-libc-macros/math-macros.h b/libc/include/llvm-libc-macros/math-macros.h index 03c7a823e6e9..1497e32044e9 100644 --- a/libc/include/llvm-libc-macros/math-macros.h +++ b/libc/include/llvm-libc-macros/math-macros.h @@ -31,10 +31,15 @@ #define NAN __builtin_nanf("") #define FP_ILOGB0 (-INT_MAX - 1) -#define FP_ILOGBNAN INT_MAX - #define FP_LLOGB0 (-LONG_MAX - 1) + +#ifdef __FP_LOGBNAN_MIN +#define FP_ILOGBNAN (-INT_MAX - 1) +#define FP_LLOGBNAN (-LONG_MAX - 1) +#else +#define FP_ILOGBNAN INT_MAX #define FP_LLOGBNAN LONG_MAX +#endif #ifdef __FAST_MATH__ #define math_errhandling 0 diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index eb0afbb6dd6f..acdf9349fd58 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -68,6 +68,7 @@ libc_support_library( name = "llvm_libc_macros_math_macros", hdrs = ["include/llvm-libc-macros/math-macros.h"], deps = [":llvm_libc_macros_limits_macros"], + defines = ["__FP_LOGBNAN_MIN"], ) libc_support_library( -- GitLab From 8a75faf4717b8258b59cf9fbb4cbd2f189114d3f Mon Sep 17 00:00:00 2001 From: smanna12 Date: Wed, 27 Mar 2024 17:12:58 -0500 Subject: [PATCH 134/541] [NFC][CLANG] Fix null pointer dereferences (#86760) This patch replaces getAs<> with castAs<> to resolve potential static analyzer bugs for 1. Dereferencing Proto1->param_type_begin(), which is known to be nullptr 2. Dereferencing Proto2->param_type_begin(), which is known to be nullptr 3. Dereferencing a pointer issue with nullptr Proto1 when calling param_type_end() 4. Dereferencing a pointer issue with nullptr Proto2 when calling param_type_end() in clang::Sema::getMoreSpecializedTemplate(). --- clang/lib/Sema/SemaTemplateDeduction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 97f8445bf819..9a55881f6442 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5514,9 +5514,9 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate( QualType Obj2Ty; if (TPOC == TPOC_Call) { const FunctionProtoType *Proto1 = - FD1->getType()->getAs(); + FD1->getType()->castAs(); const FunctionProtoType *Proto2 = - FD2->getType()->getAs(); + FD2->getType()->castAs(); // - In the context of a function call, the function parameter types are // used. -- GitLab From 4c2f68840e984b0f111779c46845ac00e3a7547d Mon Sep 17 00:00:00 2001 From: smanna12 Date: Wed, 27 Mar 2024 17:17:27 -0500 Subject: [PATCH 135/541] [CLANG] Fix potential integer overflow value in getRVVTypeSize() (#86810) In getRVVTypeSize(clang::ASTContext &, clang::BuiltinType const *) potential integer overflow occurs on expression VScale->first * MinElts with type unsigned int (32 bits, unsigned) is evaluated using 32-bit arithmetic, and then used in a context that expects an expression of type uint64_t (64 bits, unsigned). To avoid integer overflow, this patch changes the types of variables MinElts and EltSize to uint64_t instead of the cast. The change matches what was originally done in https://github.com/llvm/llvm-project/commit/7372c0d46d2185017c509eb30910b102b4f9cdaa. Looks like the revert happened in https://github.com/llvm/llvm-project/commit/c92ad411f2f94d8521cd18abcb37285f9a390ecb --- clang/lib/AST/ASTContext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 20a5ecc99e44..c90fafb6f653 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9600,11 +9600,11 @@ static uint64_t getRVVTypeSize(ASTContext &Context, const BuiltinType *Ty) { ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty); - unsigned EltSize = Context.getTypeSize(Info.ElementType); + uint64_t EltSize = Context.getTypeSize(Info.ElementType); if (Info.ElementType == Context.BoolTy) EltSize = 1; - unsigned MinElts = Info.EC.getKnownMinValue(); + uint64_t MinElts = Info.EC.getKnownMinValue(); return VScale->first * MinElts * EltSize; } -- GitLab From d8fe2e4bb05c27520a98dc14b2354901a1d57e53 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Wed, 27 Mar 2024 15:23:49 -0700 Subject: [PATCH 136/541] [BOLT] Fix enumeration of secondary entry points Make them start with 1 instead of 0 (reserved for primary entry point). Test Plan: ``` bin/llvm-lit -a tools/bolt/test/X86/yaml-secondary-entry-discriminator.s ``` Reviewers: rafaelauler, ayermolo, maksfb, dcci Reviewed By: maksfb Pull Request: https://github.com/llvm/llvm-project/pull/86848 --- bolt/lib/Core/BinaryFunction.cpp | 6 +- .../X86/yaml-secondary-entry-discriminator.s | 71 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 bolt/test/X86/yaml-secondary-entry-discriminator.s diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index fdadef9dcd38..c9e037c225dd 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -3547,7 +3547,7 @@ MCSymbol *BinaryFunction::getSymbolForEntryID(uint64_t EntryID) { if (!isMultiEntry()) return nullptr; - uint64_t NumEntries = 0; + uint64_t NumEntries = 1; if (hasCFG()) { for (BinaryBasicBlock *BB : BasicBlocks) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(*BB); @@ -3580,7 +3580,7 @@ uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { return 0; // Check all secondary entries available as either basic blocks or lables. - uint64_t NumEntries = 0; + uint64_t NumEntries = 1; for (const BinaryBasicBlock *BB : BasicBlocks) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(*BB); if (!EntrySymbol) @@ -3589,7 +3589,7 @@ uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { return NumEntries; ++NumEntries; } - NumEntries = 0; + NumEntries = 1; for (const std::pair &KV : Labels) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(KV.second); if (!EntrySymbol) diff --git a/bolt/test/X86/yaml-secondary-entry-discriminator.s b/bolt/test/X86/yaml-secondary-entry-discriminator.s new file mode 100644 index 000000000000..55dc024b325e --- /dev/null +++ b/bolt/test/X86/yaml-secondary-entry-discriminator.s @@ -0,0 +1,71 @@ +# This reproduces a bug with BOLT setting incorrect discriminator for +# secondary entry points in YAML profile. + +# REQUIRES: system-linux +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata -w %t.yaml --print-profile \ +# RUN: --print-only=main | FileCheck %s --check-prefix=CHECK-CFG +# RUN: FileCheck %s -input-file %t.yaml +# CHECK: - name: main +# CHECK-NEXT: fid: 2 +# CHECK-NEXT: hash: 0xADF270D550151185 +# CHECK-NEXT: exec: 0 +# CHECK-NEXT: nblocks: 4 +# CHECK-NEXT: blocks: +# CHECK: - bid: 1 +# CHECK-NEXT: insns: 1 +# CHECK-NEXT: hash: 0x36A303CBA4360014 +# CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1 } ] + +# Make sure that the profile is attached correctly +# RUN: llvm-bolt %t.exe -o %t.out --data %t.yaml --print-profile \ +# RUN: --print-only=main | FileCheck %s --check-prefix=CHECK-CFG + +# CHECK-CFG: Binary Function "main" after attaching profile { +# CHECK-CFG: callq secondary_entry # Offset: [[#]] # Count: 1 +# CHECK-CFG: callq *%rax # Offset: [[#]] # CallProfile: 1 (1 misses) : +# XXX: uncomment after discriminator is set correctly for indirect calls +# COM: CHECK-CFG-NEXT: { secondary_entry: 1 (1 misses) } +# CHECK-CFG: } + +.globl func +.type func, @function +func: + .cfi_startproc + pushq %rbp + movq %rsp, %rbp +.globl secondary_entry +secondary_entry: + popq %rbp + retq + nopl (%rax) + .cfi_endproc + .size func, .-func + +.globl main +.type main, @function +main: + .cfi_startproc + pushq %rbp + movq %rsp, %rbp + subq $16, %rsp + movl $0, -4(%rbp) + testq %rax, %rax + jne Lindcall +Lcall: + call secondary_entry +# FDATA: 1 main #Lcall# 1 secondary_entry 0 1 1 +Lindcall: + callq *%rax +# FDATA: 1 main #Lindcall# 1 secondary_entry 0 1 1 + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq +# For relocations against .text + call exit + .cfi_endproc + .size main, .-main -- GitLab From 0a17eedf7b0c1168999e7ac0492015c64c1fbef4 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Wed, 27 Mar 2024 23:53:25 +0100 Subject: [PATCH 137/541] [CI][NFC] Fix shellcheck warnings in CI scripts (#86877) This fixes all shellcheck warnings we have in `monolithic-linux.sh` and `monolithic-windows.sh`. All of them have to do with [SC2086](https://www.shellcheck.net/wiki/SC2086) - Double quote to prevent globbing and word splitting. --- .ci/monolithic-linux.sh | 8 ++++---- .ci/monolithic-windows.sh | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 9e670c447fba..35f1aacb4985 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -18,7 +18,7 @@ set -o pipefail MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" -rm -rf ${BUILD_DIR} +rm -rf "${BUILD_DIR}" ccache --zero-stats @@ -37,8 +37,8 @@ projects="${1}" targets="${2}" echo "--- cmake" -pip install -q -r ${MONOREPO_ROOT}/mlir/python/requirements.txt -cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ +pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt +cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_PROJECTS="${projects}" \ -G Ninja \ -D CMAKE_BUILD_TYPE=Release \ @@ -54,4 +54,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" -k 0 ${targets} +ninja -C "${BUILD_DIR}" -k 0 "${targets}" diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 52ba13036f91..f84c0966704e 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -19,7 +19,7 @@ set -o pipefail MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" -rm -rf ${BUILD_DIR} +rm -rf "${BUILD_DIR}" if [[ -n "${CLEAR_CACHE:-}" ]]; then echo "clearing sccache" @@ -37,14 +37,14 @@ projects="${1}" targets="${2}" echo "--- cmake" -pip install -q -r ${MONOREPO_ROOT}/mlir/python/requirements.txt +pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt # The CMAKE_*_LINKER_FLAGS to disable the manifest come from research # on fixing a build reliability issue on the build server, please # see https://github.com/llvm/llvm-project/pull/82393 and # https://discourse.llvm.org/t/rfc-future-of-windows-pre-commit-ci/76840/40 # for further information. -cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ +cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_PROJECTS="${projects}" \ -G Ninja \ -D CMAKE_BUILD_TYPE=Release \ @@ -62,4 +62,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" -k 0 ${targets} +ninja -C "${BUILD_DIR}" -k 0 "${targets}" -- GitLab From 14ba782a87e16e9e15460a51f50e67e2744c26d9 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 27 Mar 2024 15:56:19 -0700 Subject: [PATCH 138/541] [Clang][Sema] Allow flexible arrays in unions and alone in structs (#84428) GNU and MSVC have extensions where flexible array members (or their equivalent) can be in unions or alone in structs. This is already fully supported in Clang through the 0-sized array ("fake flexible array") extension or when C99 flexible array members have been syntactically obfuscated. Clang needs to explicitly allow these extensions directly for C99 flexible arrays, since they are common code patterns in active use by the Linux kernel (and other projects). Such projects have been using either 0-sized arrays (which is considered deprecated in favor of C99 flexible array members) or via obfuscated syntax, both of which complicate their code bases. For example, these do not error by default: ``` union one { int a; int b[0]; }; union two { int a; struct { struct { } __empty; int b[]; }; }; ``` But this does: ``` union three { int a; int b[]; }; ``` Remove the default error diagnostics for this but continue to provide warnings under Microsoft or GNU extensions checks. This will allow for a seamless transition for code bases away from 0-sized arrays without losing existing code patterns. Add explicit checking for the warnings under various constructions. Additionally fixes a CodeGen bug with flexible array members in unions in C++, which was found when adding a testcase for: ``` union { char x[]; } z = {0}; ``` which only had Sema tests originally. Fixes #84565 --- clang/docs/ReleaseNotes.rst | 3 + .../clang/Basic/DiagnosticSemaKinds.td | 5 - clang/lib/Sema/SemaDecl.cpp | 8 +- clang/lib/Sema/SemaInit.cpp | 11 +- clang/test/C/drs/dr5xx.c | 2 +- clang/test/CodeGen/flexible-array-init.c | 89 ++++++++- clang/test/CodeGen/flexible-array-init.cpp | 24 +++ clang/test/Sema/flexible-array-in-union.c | 187 +++++++++++++++++- clang/test/Sema/transparent-union.c | 4 +- 9 files changed, 303 insertions(+), 30 deletions(-) create mode 100644 clang/test/CodeGen/flexible-array-init.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0fdd9e3fb3ee..ccc399d36dbb 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -304,6 +304,9 @@ Improvements to Clang's diagnostics annotated with the ``clang::always_destroy`` attribute. Fixes #GH68686, #GH86486 +- ``-Wmicrosoft``, ``-Wgnu``, or ``-pedantic`` is now required to diagnose C99 + flexible array members in a union or alone in a struct. Fixes GH#84565. + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fc727cef9cd8..51af81bf1f6f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6464,9 +6464,6 @@ def ext_c99_flexible_array_member : Extension< def err_flexible_array_virtual_base : Error< "flexible array member %0 not allowed in " "%select{struct|interface|union|class|enum}1 which has a virtual base class">; -def err_flexible_array_empty_aggregate : Error< - "flexible array member %0 not allowed in otherwise empty " - "%select{struct|interface|union|class|enum}1">; def err_flexible_array_has_nontrivial_dtor : Error< "flexible array member %0 of type %1 with non-trivial destruction">; def ext_flexible_array_in_struct : Extension< @@ -6481,8 +6478,6 @@ def ext_flexible_array_empty_aggregate_ms : Extension< "flexible array member %0 in otherwise empty " "%select{struct|interface|union|class|enum}1 is a Microsoft extension">, InGroup; -def err_flexible_array_union : Error< - "flexible array member %0 in a union is not allowed">; def ext_flexible_array_union_ms : Extension< "flexible array member %0 in a union is a Microsoft extension">, InGroup; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8b44d24f5273..0bd88ece2aa5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19429,15 +19429,11 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, } else if (Record->isUnion()) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_union_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_union_gnu - : diag::err_flexible_array_union; + : diag::ext_flexible_array_union_gnu; else if (NumNamedMembers < 1) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_empty_aggregate_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_empty_aggregate_gnu - : diag::err_flexible_array_empty_aggregate; + : diag::ext_flexible_array_empty_aggregate_gnu; if (DiagID) Diag(FD->getLocation(), DiagID) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 2b4805d62d07..dce225a7204d 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2329,11 +2329,11 @@ void InitListChecker::CheckStructUnionTypes( break; } - // We've already initialized a member of a union. We're done. + // We've already initialized a member of a union. We can stop entirely. if (InitializedSomething && RD->isUnion()) - break; + return; - // If we've hit the flexible array member at the end, we're done. + // Stop if we've hit a flexible array member. if (Field->getType()->isIncompleteArrayType()) break; @@ -2456,6 +2456,11 @@ void InitListChecker::CheckStructUnionTypes( else CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); + + if (RD->isUnion() && StructuredList) { + // Initialize the first field within the union. + StructuredList->setInitializedFieldInUnion(*Field); + } } /// Expand a field designator that refers to a member of an diff --git a/clang/test/C/drs/dr5xx.c b/clang/test/C/drs/dr5xx.c index 68bcef78bacc..13464f78b6a6 100644 --- a/clang/test/C/drs/dr5xx.c +++ b/clang/test/C/drs/dr5xx.c @@ -29,7 +29,7 @@ void dr502(void) { */ struct t { int i; - struct { int a[]; }; /* expected-error {{flexible array member 'a' not allowed in otherwise empty struct}} + struct { int a[]; }; /* expected-warning {{flexible array member 'a' in otherwise empty struct is a GNU extension}} c89only-warning {{flexible array members are a C99 feature}} expected-warning {{'' may not be nested in a struct due to flexible array member}} */ diff --git a/clang/test/CodeGen/flexible-array-init.c b/clang/test/CodeGen/flexible-array-init.c index bae926da5feb..15a30c15ac96 100644 --- a/clang/test/CodeGen/flexible-array-init.c +++ b/clang/test/CodeGen/flexible-array-init.c @@ -3,9 +3,15 @@ struct { int x; int y[]; } a = { 1, 7, 11 }; // CHECK: @a ={{.*}} global { i32, [2 x i32] } { i32 1, [2 x i32] [i32 7, i32 11] } +struct { int y[]; } a1 = { 8, 12 }; +// CHECK: @a1 ={{.*}} global { [2 x i32] } { [2 x i32] [i32 8, i32 12] } + struct { int x; int y[]; } b = { 1, { 13, 15 } }; // CHECK: @b ={{.*}} global { i32, [2 x i32] } { i32 1, [2 x i32] [i32 13, i32 15] } +struct { int y[]; } b1 = { { 14, 16 } }; +// CHECK: @b1 ={{.*}} global { [2 x i32] } { [2 x i32] [i32 14, i32 16] } + // sizeof(c) == 8, so this global should be at least 8 bytes. struct { int x; char c; char y[]; } c = { 1, 2, { 13, 15 } }; // CHECK: @c ={{.*}} global { i32, i8, [2 x i8] } { i32 1, i8 2, [2 x i8] c"\0D\0F" } @@ -21,10 +27,79 @@ struct __attribute((packed, aligned(4))) { char a; int x; char z[]; } e = { 1, 2 struct { int x; char y[]; } f = { 1, { 13, 15 } }; // CHECK: @f ={{.*}} global <{ i32, [2 x i8] }> <{ i32 1, [2 x i8] c"\0D\0F" }> -union { - struct { - int a; - char b[]; - } x; -} in_union = {}; -// CHECK: @in_union ={{.*}} global %union.anon zeroinitializer +struct __attribute((packed)) { short a; char z[]; } g = { 2, { 11, 13, 15 } }; +// CHECK: @g ={{.*}} <{ i16, [3 x i8] }> <{ i16 2, [3 x i8] c"\0B\0D\0F" }>, + +// Last member is the potential flexible array, unnamed initializer skips it. +struct { int a; union { int b; short x; }; int c; int d; } h = {1, 2, {}, 3}; +// CHECK: @h = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[0]; }; int c; int d; } h0 = {1, 2, {}, 3}; +// CHECK: @h0 = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[1]; }; int c; int d; } h1 = {1, 2, {}, 3}; +// CHECK: @h1 = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { + int a; + union { + int b; + struct { + struct { } __ununsed; + short x[]; + }; + }; + int c; + int d; +} hiding = {1, 2, {}, 3}; +// CHECK: @hiding = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[]; }; int c; int d; } hf = {1, 2, {}, 3}; +// CHECK: @hf = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } + +// First member is the potential flexible array, initialization requires braces. +struct { int a; union { short x; int b; }; int c; int d; } i = {1, 2, {}, 3}; +// CHECK: @i = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 0, i32 3 } +struct { int a; union { short x[0]; int b; }; int c; int d; } i0 = {1, {}, 2, 3}; +// CHECK: @i0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 2, i32 3 } +struct { int a; union { short x[1]; int b; }; int c; int d; } i1 = {1, {2}, {}, 3}; +// CHECK: @i1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 0, i32 3 } +struct { int a; union { short x[]; int b; }; int c; int d; } i_f = {4, {}, {}, 6}; +// CHECK: @i_f = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 4, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 0, i32 6 } + +// Named initializers; order doesn't matter. +struct { int a; union { int b; short x; }; int c; int d; } hn = {.a = 1, .x = 2, .c = 3}; +// CHECK: @hn = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 3, i32 0 } +struct { int a; union { int b; short x[0]; }; int c; int d; } hn0 = {.a = 1, .x = {2}, .c = 3}; +// CHECK: @hn0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 3, i32 0 } +struct { int a; union { int b; short x[1]; }; int c; int d; } hn1 = {.a = 1, .x = {2}, .c = 3}; +// CHECK: @hn1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 3, i32 0 } + +struct { char a[]; } empty_struct = {}; +// CHECK: @empty_struct ={{.*}} global %struct.anon{{.*}} zeroinitializer, align 1 + +struct { char a[]; } empty_struct0 = {0}; +// CHECK: @empty_struct0 = global { [1 x i8] } zeroinitializer, align 1 + +union { struct { int a; char b[]; }; } struct_in_union = {}; +// CHECK: @struct_in_union = global %union.anon{{.*}} zeroinitializer, align 4 + +union { struct { int a; char b[]; }; } struct_in_union0 = {0}; +// CHECK: @struct_in_union0 = global %union.anon{{.*}} zeroinitializer, align 4 + +union { int a; char b[]; } trailing_in_union = {}; +// CHECK: @trailing_in_union = global %union.anon{{.*}} zeroinitializer, align 4 + +union { int a; char b[]; } trailing_in_union0 = {0}; +// CHECK: @trailing_in_union0 = global %union.anon{{.*}} zeroinitializer, align 4 + +union { char a[]; } only_in_union = {}; +// CHECK: @only_in_union = global %union.anon{{.*}} zeroinitializer, align 1 + +union { char a[]; } only_in_union0 = {0}; +// CHECK: @only_in_union0 = global { [1 x i8] } zeroinitializer, align 1 + +union { char a[]; int b; } first_in_union = {}; +// CHECK: @first_in_union = global { [0 x i8], [4 x i8] } { [0 x i8] zeroinitializer, [4 x i8] undef }, align 4 + +union { char a[]; int b; } first_in_union0 = {0}; +// CHECK: @first_in_union0 = global { [1 x i8], [3 x i8] } { [1 x i8] zeroinitializer, [3 x i8] undef }, align 4 + +union { char a[]; int b; } first_in_union123 = { {1, 2, 3} }; +// CHECK: @first_in_union123 = global { [3 x i8], i8 } { [3 x i8] c"\01\02\03", i8 undef }, align 4 diff --git a/clang/test/CodeGen/flexible-array-init.cpp b/clang/test/CodeGen/flexible-array-init.cpp new file mode 100644 index 000000000000..d067a614e1af --- /dev/null +++ b/clang/test/CodeGen/flexible-array-init.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -x c++ -emit-llvm -o - %s | FileCheck %s + +union _u { char a[]; } u = {}; +union _u0 { char a[]; } u0 = {0}; + +// CHECK: %union._u = type { [0 x i8] } + +// CHECK: @u = global %union._u zeroinitializer, align 1 +// CHECK: @u0 = global { [1 x i8] } zeroinitializer, align 1 + +union { char a[]; } z = {}; +// CHECK: @z = internal global %union.{{.*}} zeroinitializer, align 1 +union { char a[]; } z0 = {0}; +// CHECK: @z0 = internal global { [1 x i8] } zeroinitializer, align 1 + +/* C++ requires global anonymous unions have static storage, so we have to + reference them to keep them in the IR output. */ +char keep(int pick) +{ + if (pick) + return z.a[0]; + else + return z0.a[0]; +} diff --git a/clang/test/Sema/flexible-array-in-union.c b/clang/test/Sema/flexible-array-in-union.c index 5fabfbe0b1ea..dd5e8069665f 100644 --- a/clang/test/Sema/flexible-array-in-union.c +++ b/clang/test/Sema/flexible-array-in-union.c @@ -1,13 +1,188 @@ -// RUN: %clang_cc1 %s -verify=c -fsyntax-only -// RUN: %clang_cc1 %s -verify -fsyntax-only -x c++ -// RUN: %clang_cc1 %s -verify -fsyntax-only -fms-compatibility -// RUN: %clang_cc1 %s -verify -fsyntax-only -fms-compatibility -x c++ +// RUN: %clang_cc1 %s -verify=stock,c -fsyntax-only +// RUN: %clang_cc1 %s -verify=stock,cpp -fsyntax-only -x c++ +// RUN: %clang_cc1 %s -verify=stock,cpp -fsyntax-only -fms-compatibility -x c++ +// RUN: %clang_cc1 %s -verify=stock,c,gnu -fsyntax-only -Wgnu-flexible-array-union-member -Wgnu-empty-struct +// RUN: %clang_cc1 %s -verify=stock,c,microsoft -fsyntax-only -fms-compatibility -Wmicrosoft // The test checks that an attempt to initialize union with flexible array // member with an initializer list doesn't crash clang. -union { char x[]; } r = {0}; // c-error {{flexible array member 'x' in a union is not allowed}} +union { char x[]; } r = {0}; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ +struct _name1 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name1 = { + 10, + 42, /* initializes "b" */ +}; -// expected-no-diagnostics +struct _name1i { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name1i = { + .a = 10, + .b = 42, +}; + +/* Initialization of flexible array in a union is never allowed. */ +struct _name2 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name2 = { + 12, + 13, + { 'c' }, /* c-warning {{excess elements in struct initializer}} + cpp-error {{excess elements in struct initializer}} + */ +}; + +/* Initialization of flexible array in a union is never allowed. */ +struct _name2i { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + stock-note {{initialized flexible array member 'x' is here}} + */ + }; +} name2i = { + .a = 12, + .b = 13, /* stock-note {{previous initialization is here}} */ + .x = { 'c' }, /* stock-error {{initialization of flexible array member is not allowed}} + c-warning {{initializer overrides prior initialization of this subobject}} + cpp-error {{initializer partially overrides prior initialization of this subobject}} + */ +}; + +/* Flexible array initialization always allowed when not in a union, + and when struct has another member. + */ +struct _okay { + int a; + char x[]; +} okay = { + 22, + { 'x', 'y', 'z' }, +}; + +struct _okayi { + int a; + char x[]; +} okayi = { + .a = 22, + .x = { 'x', 'y', 'z' }, +}; + +struct _okay0 { + int a; + char x[]; +} okay0 = { }; + +struct _flex_extension { + char x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +} flex_extension = { + { 'x', 'y', 'z' }, +}; + +struct _flex_extensioni { + char x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +} flex_extensioni = { + .x = { 'x', 'y', 'z' }, +}; + +struct already_hidden { + int a; + union { + int b; + struct { + struct { } __empty; // gnu-warning {{empty struct is a GNU extension}} + char x[]; + }; + }; +}; +struct still_zero_sized { + struct { } __unused; // gnu-warning {{empty struct is a GNU extension}} + int x[]; +}; + +struct warn1 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +}; + +struct warn2 { + int x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +}; + +union warn3 { + short x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ +}; + +struct quiet1 { + int a; + short x[]; +}; + +struct _not_at_end { + union { short x[]; }; /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} + gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + int y; +} not_at_end = {{}, 3}; + +struct _not_at_end_s { + struct { int a; short x[]; }; /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} */ + int y; +} not_at_end_s = {{}, 3}; + +struct { + int a; + union { /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} */ + short x[]; /* stock-note {{initialized flexible array member 'x' is here}} + gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + int b; + }; + int c; + int d; +} i_f = { 4, + {5}, /* stock-error {{initialization of flexible array member is not allowed}} */ + {}, + 6}; + +// expected-no-diagnostics diff --git a/clang/test/Sema/transparent-union.c b/clang/test/Sema/transparent-union.c index c134a7a9b1c4..f02c2298b51c 100644 --- a/clang/test/Sema/transparent-union.c +++ b/clang/test/Sema/transparent-union.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wgnu-flexible-array-union-member %s typedef union { int *ip; float *fp; @@ -131,7 +131,7 @@ union pr15134v2 { union pr30520v { void b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'void'}} -union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-error {{flexible array member 'b' in a union is not allowed}} +union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-warning {{flexible array member 'b' in a union is a GNU extension}} // expected-note@+1 2 {{forward declaration of 'struct stb'}} union pr30520s { struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}} -- GitLab From b76fd1eddbafaa02a533245d574048c5ad9e38fa Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 27 Mar 2024 16:37:00 -0700 Subject: [PATCH 139/541] [lldb] Avoid deadlock by unlocking before invoking callbacks (#86888) Avoid deadlocks in the Alarm class by releasing the lock before invoking callbacks. This deadlock manifested itself in the ProgressManager: 1. On the main thread, the ProgressManager acquires its lock in ProgressManager::Decrement and calls Alarm::Create. 2. On the main thread, the Alarm acquires its lock in Alarm::Create. 3. On the alarm thread, the Alarm acquires its lock after waiting on the condition variable and calls ProgressManager::Expire. 4. On the alarm thread, the ProgressManager acquires its lock in ProgressManager::Expire. Note how the two threads are acquiring the locks in different orders. Deadlocks can be avoided by always acquiring locks in the same order, but since the two mutexes here are private implementation details, belong to different classes, that's not straightforward. Luckily, we don't need to have the Alarm mutex locked when invoking the callbacks. That exactly how this patch solves the issue. --- lldb/source/Host/common/Alarm.cpp | 84 +++++++++++++++++-------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/lldb/source/Host/common/Alarm.cpp b/lldb/source/Host/common/Alarm.cpp index 245cdc7ae5c2..afc770d20d7b 100644 --- a/lldb/source/Host/common/Alarm.cpp +++ b/lldb/source/Host/common/Alarm.cpp @@ -154,54 +154,60 @@ lldb::thread_result_t Alarm::AlarmThread() { // // Below we only deal with the timeout expiring and fall through for dealing // with the rest. - std::unique_lock alarm_lock(m_alarm_mutex); - if (next_alarm) { - if (!m_alarm_cv.wait_until(alarm_lock, *next_alarm, predicate)) { - // The timeout for the next alarm expired. - - // Clear the next timeout to signal that we need to recompute the next - // timeout. - next_alarm.reset(); - - // Iterate over all the callbacks. Call the ones that have expired - // and remove them from the list. - const TimePoint now = std::chrono::system_clock::now(); - auto it = m_entries.begin(); - while (it != m_entries.end()) { - if (it->expiration <= now) { - it->callback(); - it = m_entries.erase(it); - } else { - it++; + llvm::SmallVector callbacks; + { + std::unique_lock alarm_lock(m_alarm_mutex); + if (next_alarm) { + if (!m_alarm_cv.wait_until(alarm_lock, *next_alarm, predicate)) { + // The timeout for the next alarm expired. + + // Clear the next timeout to signal that we need to recompute the next + // timeout. + next_alarm.reset(); + + // Iterate over all the callbacks. Call the ones that have expired + // and remove them from the list. + const TimePoint now = std::chrono::system_clock::now(); + auto it = m_entries.begin(); + while (it != m_entries.end()) { + if (it->expiration <= now) { + callbacks.emplace_back(std::move(it->callback)); + it = m_entries.erase(it); + } else { + it++; + } } } + } else { + m_alarm_cv.wait(alarm_lock, predicate); } - } else { - m_alarm_cv.wait(alarm_lock, predicate); - } - // Fall through after waiting on the condition variable. At this point - // either the predicate is true or we woke up because an alarm expired. + // Fall through after waiting on the condition variable. At this point + // either the predicate is true or we woke up because an alarm expired. - // The alarm thread is shutting down. - if (m_exit) { - exit = true; - if (m_run_callbacks_on_exit) { - for (Entry &entry : m_entries) - entry.callback(); + // The alarm thread is shutting down. + if (m_exit) { + exit = true; + if (m_run_callbacks_on_exit) { + for (Entry &entry : m_entries) + callbacks.emplace_back(std::move(entry.callback)); + } } - continue; - } - // A new alarm was added or an alarm expired. Either way we need to - // recompute when this thread should wake up for the next alarm. - if (m_recompute_next_alarm || !next_alarm) { - for (Entry &entry : m_entries) { - if (!next_alarm || entry.expiration < *next_alarm) - next_alarm = entry.expiration; + // A new alarm was added or an alarm expired. Either way we need to + // recompute when this thread should wake up for the next alarm. + if (m_recompute_next_alarm || !next_alarm) { + for (Entry &entry : m_entries) { + if (!next_alarm || entry.expiration < *next_alarm) + next_alarm = entry.expiration; + } + m_recompute_next_alarm = false; } - m_recompute_next_alarm = false; } + + // Outside the lock, call the callbacks. + for (Callback &callback : callbacks) + callback(); } return {}; } -- GitLab From 385e3e26c11fac9373bf7ba431b90b6f42682c84 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Wed, 27 Mar 2024 16:40:38 -0700 Subject: [PATCH 140/541] [BOLT] Set EntryDiscriminator in YAML profile for indirect calls Indirect call handling missed setting an `EntryDiscriminator` while it's set for direct calls and tail calls. Improve YAML profile accuracy by unifying the destination setting between direct and indirect calls into `setCSIDestination` method. Depends on: https://github.com/llvm/llvm-project/pull/86848 Test Plan: Updated bolt/test/X86/yaml-secondary-entry-discriminator.s Reviewers: ayermolo, maksfb, rafaelauler Reviewed By: maksfb Pull Request: https://github.com/llvm/llvm-project/pull/82128 --- bolt/lib/Profile/YAMLProfileWriter.cpp | 40 +++++++++++-------- .../X86/yaml-secondary-entry-discriminator.s | 9 +++-- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index 6fcc4a956fa1..0f082086c1fc 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -25,6 +25,25 @@ extern llvm::cl::opt ProfileUseDFS; namespace llvm { namespace bolt { +/// Set CallSiteInfo destination fields from \p Symbol and return a target +/// BinaryFunction for that symbol. +static const BinaryFunction *setCSIDestination(const BinaryContext &BC, + yaml::bolt::CallSiteInfo &CSI, + const MCSymbol *Symbol) { + CSI.DestId = 0; // designated for unknown functions + CSI.EntryDiscriminator = 0; + if (Symbol) { + uint64_t EntryID = 0; + if (const BinaryFunction *const Callee = + BC.getFunctionForSymbol(Symbol, &EntryID)) { + CSI.DestId = Callee->getFunctionNumber(); + CSI.EntryDiscriminator = EntryID; + return Callee; + } + } + return nullptr; +} + yaml::bolt::BinaryFunctionProfile YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS) { yaml::bolt::BinaryFunctionProfile YamlBF; @@ -79,31 +98,20 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS) { continue; for (const IndirectCallProfile &CSP : ICSP.get()) { StringRef TargetName = ""; - CSI.DestId = 0; // designated for unknown functions - CSI.EntryDiscriminator = 0; - if (CSP.Symbol) { - const BinaryFunction *Callee = BC.getFunctionForSymbol(CSP.Symbol); - if (Callee) { - CSI.DestId = Callee->getFunctionNumber(); - TargetName = Callee->getOneName(); - } - } + const BinaryFunction *Callee = setCSIDestination(BC, CSI, CSP.Symbol); + if (Callee) + TargetName = Callee->getOneName(); CSI.Count = CSP.Count; CSI.Mispreds = CSP.Mispreds; CSTargets.emplace_back(TargetName, CSI); } } else { // direct call or a tail call - uint64_t EntryID = 0; - CSI.DestId = 0; StringRef TargetName = ""; const MCSymbol *CalleeSymbol = BC.MIB->getTargetSymbol(Instr); const BinaryFunction *const Callee = - BC.getFunctionForSymbol(CalleeSymbol, &EntryID); - if (Callee) { - CSI.DestId = Callee->getFunctionNumber(); - CSI.EntryDiscriminator = EntryID; + setCSIDestination(BC, CSI, CalleeSymbol); + if (Callee) TargetName = Callee->getOneName(); - } auto getAnnotationWithDefault = [&](const MCInst &Inst, StringRef Ann) { return BC.MIB->getAnnotationWithDefault(Instr, Ann, 0ull); diff --git a/bolt/test/X86/yaml-secondary-entry-discriminator.s b/bolt/test/X86/yaml-secondary-entry-discriminator.s index 55dc024b325e..43c2e2a7f055 100644 --- a/bolt/test/X86/yaml-secondary-entry-discriminator.s +++ b/bolt/test/X86/yaml-secondary-entry-discriminator.s @@ -19,6 +19,10 @@ # CHECK-NEXT: insns: 1 # CHECK-NEXT: hash: 0x36A303CBA4360014 # CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1 } ] +# CHECK: - bid: 2 +# CHECK-NEXT: insns: 5 +# CHECK-NEXT: hash: 0x8B2F5747CD0019 +# CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1, mis: 1 } ] # Make sure that the profile is attached correctly # RUN: llvm-bolt %t.exe -o %t.out --data %t.yaml --print-profile \ @@ -27,13 +31,12 @@ # CHECK-CFG: Binary Function "main" after attaching profile { # CHECK-CFG: callq secondary_entry # Offset: [[#]] # Count: 1 # CHECK-CFG: callq *%rax # Offset: [[#]] # CallProfile: 1 (1 misses) : -# XXX: uncomment after discriminator is set correctly for indirect calls -# COM: CHECK-CFG-NEXT: { secondary_entry: 1 (1 misses) } -# CHECK-CFG: } +# CHECK-CFG-NEXT: { secondary_entry: 1 (1 misses) } .globl func .type func, @function func: +# FDATA: 0 [unknown] 0 1 func 0 1 0 .cfi_startproc pushq %rbp movq %rsp, %rbp -- GitLab From 19185d5a72565fce34521cb59d6c87232a86e0d4 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Wed, 27 Mar 2024 18:40:57 -0500 Subject: [PATCH 141/541] [Libomptarget] Make dynamic loading libffi more verbose. (#86891) --- .../plugins-nextgen/host/dynamic_ffi/ffi.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp b/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp index c79daa798581..c586ad1c1969 100644 --- a/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp +++ b/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/DynamicLibrary.h" + +#include "Shared/Debug.h" #include #include "DLWrap.h" @@ -37,15 +39,21 @@ uint32_t ffi_init() { std::string ErrMsg; auto DynlibHandle = std::make_unique( llvm::sys::DynamicLibrary::getPermanentLibrary(FFI_PATH, &ErrMsg)); - if (!DynlibHandle->isValid()) + + if (!DynlibHandle->isValid()) { + DP("Unable to load library '%s': %s!\n", FFI_PATH, ErrMsg.c_str()); return DYNAMIC_FFI_FAIL; + } for (size_t I = 0; I < dlwrap::size(); I++) { const char *Sym = dlwrap::symbol(I); void *P = DynlibHandle->getAddressOfSymbol(Sym); - if (P == nullptr) + if (P == nullptr) { + DP("Unable to find '%s' in '%s'!\n", Sym, FFI_PATH); return DYNAMIC_FFI_FAIL; + } + DP("Implementing %s with dlsym(%s) -> %p\n", Sym, Sym, P); *dlwrap::pointer(I) = P; } @@ -53,8 +61,10 @@ uint32_t ffi_init() { #define DYNAMIC_INIT(SYMBOL) \ { \ void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ - if (!SymbolPtr) \ + if (!SymbolPtr) { \ + DP("Unable to find '%s' in '%s'!\n", #SYMBOL, FFI_PATH); \ return DYNAMIC_FFI_FAIL; \ + } \ SYMBOL = *reinterpret_cast(SymbolPtr); \ } DYNAMIC_INIT(ffi_type_void); -- GitLab From e318613418e08e20d3b9e139a1a3ef0208db4844 Mon Sep 17 00:00:00 2001 From: Alex MacLean Date: Wed, 27 Mar 2024 16:49:59 -0700 Subject: [PATCH 142/541] [NFC][TLI] Move VecFuncs to statics to reduce stack usage (#86829) `TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib` has a lot of data in local stack arrays, which MSVC keeps on the stack even in release builds. To reduce stack usage, the data arrays (which are const), are moved outside the function as statics. This drops the method stack usage to be negligible. --- llvm/lib/Analysis/TargetLibraryInfo.cpp | 130 +++++++++++++----------- 1 file changed, 68 insertions(+), 62 deletions(-) diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index c8195584ade3..9e17dcaa5592 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -1190,107 +1190,113 @@ void TargetLibraryInfoImpl::addVectorizableFunctions(ArrayRef Fns) { llvm::sort(ScalarDescs, compareByVectorFnName); } +static const VecDesc VecFuncs_Accelerate[] = { +#define TLI_DEFINE_ACCELERATE_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_DarwinLibSystemM[] = { +#define TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_LIBMVEC_X86[] = { +#define TLI_DEFINE_LIBMVEC_X86_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_MASSV[] = { +#define TLI_DEFINE_MASSV_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_SVML[] = { +#define TLI_DEFINE_SVML_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_SLEEFGNUABI_VF2[] = { +#define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ + {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; +static const VecDesc VecFuncs_SLEEFGNUABI_VF4[] = { +#define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ + {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; +static const VecDesc VecFuncs_SLEEFGNUABI_VFScalable[] = { +#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ + {SCAL, VEC, VF, MASK, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_ArmPL[] = { +#define TLI_DEFINE_ARMPL_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ + {SCAL, VEC, VF, MASK, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; + +const VecDesc VecFuncs_AMDLIBM[] = { +#define TLI_DEFINE_AMDLIBM_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ + {SCAL, VEC, VF, MASK, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; + void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib( enum VectorLibrary VecLib, const llvm::Triple &TargetTriple) { switch (VecLib) { case Accelerate: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_ACCELERATE_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_Accelerate); break; } case DarwinLibSystemM: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_DarwinLibSystemM); break; } case LIBMVEC_X86: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_LIBMVEC_X86_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_LIBMVEC_X86); break; } case MASSV: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_MASSV_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_MASSV); break; } case SVML: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_SVML_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_SVML); break; } case SLEEFGNUABI: { - const VecDesc VecFuncs_VF2[] = { -#define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ - {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - const VecDesc VecFuncs_VF4[] = { -#define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ - {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - const VecDesc VecFuncs_VFScalable[] = { -#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ - {SCAL, VEC, VF, MASK, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - switch (TargetTriple.getArch()) { default: break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - addVectorizableFunctions(VecFuncs_VF2); - addVectorizableFunctions(VecFuncs_VF4); - addVectorizableFunctions(VecFuncs_VFScalable); + addVectorizableFunctions(VecFuncs_SLEEFGNUABI_VF2); + addVectorizableFunctions(VecFuncs_SLEEFGNUABI_VF4); + addVectorizableFunctions(VecFuncs_SLEEFGNUABI_VFScalable); break; } break; } case ArmPL: { - const VecDesc VecFuncs[] = { -#define TLI_DEFINE_ARMPL_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ - {SCAL, VEC, VF, MASK, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - switch (TargetTriple.getArch()) { default: break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_ArmPL); break; } break; } case AMDLIBM: { - const VecDesc VecFuncs[] = { -#define TLI_DEFINE_AMDLIBM_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ - {SCAL, VEC, VF, MASK, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_AMDLIBM); break; } case NoLibrary: -- GitLab From 036e7ee9d1f1bdc194b56302f8dd27d5eb6cfdab Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 27 Mar 2024 17:06:41 -0700 Subject: [PATCH 143/541] [NFC][AArch64] Regenerate regression tests. --- .../GlobalISel/load-addressing-modes.mir | 329 ++++++++++-------- .../aarch64-split-and-bitmask-immediate.ll | 14 +- 2 files changed, 186 insertions(+), 157 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir b/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir index 0cf9602adbb0..499c08fa4966 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir @@ -40,11 +40,12 @@ body: | ; CHECK-LABEL: name: ldrxrox_breg_oreg ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $x0 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x0 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -65,11 +66,12 @@ body: | liveins: $d0, $x1 ; CHECK-LABEL: name: ldrdrox_breg_oreg ; CHECK: liveins: $d0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $d0 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d0 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d0 %0:gpr(p0) = COPY $d0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -78,6 +80,9 @@ body: | RET_ReallyLR implicit $d0 ... --- +# This shouldn't be folded, since we reuse the result of the G_PTR_ADD outside +# the G_LOAD + name: more_than_one_use alignment: 4 legalized: true @@ -87,18 +92,17 @@ machineFunctionInfo: {} body: | bb.0: liveins: $x0, $x1 - ; This shouldn't be folded, since we reuse the result of the G_PTR_ADD outside - ; the G_LOAD ; CHECK-LABEL: name: more_than_one_use ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY]], [[COPY1]] - ; CHECK: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] - ; CHECK: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[LDRXui]] - ; CHECK: $x0 = COPY [[ADDXrr1]] - ; CHECK: RET_ReallyLR implicit $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY]], [[COPY1]] + ; CHECK-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] + ; CHECK-NEXT: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[LDRXui]] + ; CHECK-NEXT: $x0 = COPY [[ADDXrr1]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -121,11 +125,12 @@ body: | liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: ldrxrox_shl ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $x2 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x2 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -148,11 +153,12 @@ body: | liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: ldrdrox_shl ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -175,11 +181,12 @@ body: | liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: ldrxrox_mul_rhs ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $x2 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x2 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %0, %1(s64) @@ -202,11 +209,12 @@ body: | liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: ldrdrox_mul_rhs ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %0, %1(s64) @@ -229,11 +237,12 @@ body: | liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: ldrxrox_mul_lhs ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $x2 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x2 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -256,11 +265,12 @@ body: | liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: ldrdrox_mul_lhs ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -272,6 +282,9 @@ body: | ... --- +# Show that we don't get a shifted load from a mul when we don't have a +# power of 2. (The bit isn't set on the load.) + name: mul_not_pow_2 alignment: 4 legalized: true @@ -280,19 +293,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we don't get a shifted load from a mul when we don't have a - ; power of 2. (The bit isn't set on the load.) liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: mul_not_pow_2 ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7 - ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 - ; CHECK: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 7 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -304,6 +316,9 @@ body: | ... --- +# Show that we don't get a shifted load from a mul when we don't have +# the right power of 2. (The bit isn't set on the load.) + name: mul_wrong_pow_2 alignment: 4 legalized: true @@ -312,19 +327,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we don't get a shifted load from a mul when we don't have - ; the right power of 2. (The bit isn't set on the load.) liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: mul_wrong_pow_2 ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 16 - ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 - ; CHECK: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 16 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 16 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -336,6 +350,9 @@ body: | ... --- +# Show that we can still fall back to the register-register addressing +# mode when we fail to pull in the shift. + name: more_than_one_use_shl_1 alignment: 4 legalized: true @@ -344,19 +361,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we can still fall back to the register-register addressing - ; mode when we fail to pull in the shift. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_1 ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[UBFMXri]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] - ; CHECK: $x2 = COPY [[ADDXrr]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[UBFMXri]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -370,6 +386,9 @@ body: | ... --- +# Show that when the GEP is used outside a memory op, we don't do any +# folding at all. + name: more_than_one_use_shl_2 alignment: 4 legalized: true @@ -378,22 +397,21 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that when the GEP is used outside a memory op, we don't do any - ; folding at all. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_2 ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY1]], [[UBFMXri]] - ; CHECK: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 - ; CHECK: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[ADDXri]] - ; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] - ; CHECK: [[ADDXrr2:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[ADDXrr1]] - ; CHECK: $x2 = COPY [[ADDXrr2]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY1]], [[UBFMXri]] + ; CHECK-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 + ; CHECK-NEXT: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[ADDXri]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] + ; CHECK-NEXT: [[ADDXrr2:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[ADDXrr1]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr2]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -409,6 +427,9 @@ body: | ... --- +# Show that when we have a fastpath for shift-left, we perform the folding +# if it has more than one use. + name: more_than_one_use_shl_lsl_fast alignment: 4 legalized: true @@ -417,18 +438,17 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that when we have a fastpath for shift-left, we perform the folding - ; if it has more than one use. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_lsl_fast ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: [[LDRXroX1:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[LDRXroX1]] - ; CHECK: $x2 = COPY [[ADDXrr]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[LDRXroX1:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[LDRXroX1]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -442,6 +462,9 @@ body: | ... --- +# Show that we don't fold into multiple memory ops when we don't have a +# fastpath for shift-left. + name: more_than_one_use_shl_lsl_slow alignment: 4 legalized: true @@ -450,19 +473,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we don't fold into multiple memory ops when we don't have a - ; fastpath for shift-left. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_lsl_slow ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[ADDXrs:%[0-9]+]]:gpr64common = ADDXrs [[COPY1]], [[COPY]], 3 - ; CHECK: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[LDRXui1:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[LDRXui1]] - ; CHECK: $x2 = COPY [[ADDXrr]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ADDXrs:%[0-9]+]]:gpr64common = ADDXrs [[COPY1]], [[COPY]], 3 + ; CHECK-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[LDRXui1:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[LDRXui1]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -476,6 +498,9 @@ body: | ... --- +# Show that when we're optimizing for size, we'll do the folding no matter +# what. + name: more_than_one_use_shl_minsize alignment: 4 legalized: true @@ -484,22 +509,21 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that when we're optimizing for size, we'll do the folding no matter - ; what. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_minsize ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64common = COPY $x1 - ; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[COPY1]] - ; CHECK: [[ADDXrs:%[0-9]+]]:gpr64 = ADDXrs [[COPY2]], [[COPY]], 3 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] - ; CHECK: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[ADDXrs]], [[ADDXrr]] - ; CHECK: $x2 = COPY [[ADDXrr1]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64common = COPY $x1 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[COPY1]] + ; CHECK-NEXT: [[ADDXrs:%[0-9]+]]:gpr64 = ADDXrs [[COPY2]], [[COPY]], 3 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] + ; CHECK-NEXT: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[ADDXrs]], [[ADDXrr]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr1]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -525,11 +549,12 @@ body: | liveins: $x0, $x1 ; CHECK-LABEL: name: ldrwrox ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) - ; CHECK: $w2 = COPY [[LDRWroX]] - ; CHECK: RET_ReallyLR implicit $w2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) + ; CHECK-NEXT: $w2 = COPY [[LDRWroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $w2 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -549,11 +574,12 @@ body: | liveins: $d0, $x1 ; CHECK-LABEL: name: ldrsrox ; CHECK: liveins: $d0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRSroX:%[0-9]+]]:fpr32 = LDRSroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) - ; CHECK: $s2 = COPY [[LDRSroX]] - ; CHECK: RET_ReallyLR implicit $h2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRSroX:%[0-9]+]]:fpr32 = LDRSroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) + ; CHECK-NEXT: $s2 = COPY [[LDRSroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $h2 %0:gpr(p0) = COPY $d0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -573,11 +599,12 @@ body: | liveins: $x0, $x1 ; CHECK-LABEL: name: ldrhrox ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRHroX:%[0-9]+]]:fpr16 = LDRHroX [[COPY]], [[COPY1]], 0, 0 :: (load (s16) from %ir.addr) - ; CHECK: $h2 = COPY [[LDRHroX]] - ; CHECK: RET_ReallyLR implicit $h2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRHroX:%[0-9]+]]:fpr16 = LDRHroX [[COPY]], [[COPY1]], 0, 0 :: (load (s16) from %ir.addr) + ; CHECK-NEXT: $h2 = COPY [[LDRHroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $h2 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -597,11 +624,12 @@ body: | liveins: $x0, $x1 ; CHECK-LABEL: name: ldbbrox ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRBBroX:%[0-9]+]]:gpr32 = LDRBBroX [[COPY]], [[COPY1]], 0, 0 :: (load (s8) from %ir.addr) - ; CHECK: $w2 = COPY [[LDRBBroX]] - ; CHECK: RET_ReallyLR implicit $w2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRBBroX:%[0-9]+]]:gpr32 = LDRBBroX [[COPY]], [[COPY1]], 0, 0 :: (load (s8) from %ir.addr) + ; CHECK-NEXT: $w2 = COPY [[LDRBBroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $w2 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -621,11 +649,12 @@ body: | liveins: $d0, $x1 ; CHECK-LABEL: name: ldrqrox ; CHECK: liveins: $d0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRQroX:%[0-9]+]]:fpr128 = LDRQroX [[COPY]], [[COPY1]], 0, 0 :: (load (<2 x s64>) from %ir.addr) - ; CHECK: $q0 = COPY [[LDRQroX]] - ; CHECK: RET_ReallyLR implicit $q0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRQroX:%[0-9]+]]:fpr128 = LDRQroX [[COPY]], [[COPY1]], 0, 0 :: (load (<2 x s64>) from %ir.addr) + ; CHECK-NEXT: $q0 = COPY [[LDRQroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:gpr(p0) = COPY $d0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 diff --git a/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll b/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll index cf9ed4d5f0e1..573f921e638c 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll @@ -20,7 +20,7 @@ entry: define i8 @test2(i32 %a) { ; CHECK-LABEL: test2: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #135 +; CHECK-NEXT: mov w8, #135 // =0x87 ; CHECK-NEXT: and w8, w0, w8 ; CHECK-NEXT: cmp w8, #1024 ; CHECK-NEXT: cset w0, eq @@ -37,7 +37,7 @@ entry: define i8 @test3(i32 %a) { ; CHECK-LABEL: test3: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #1024 +; CHECK-NEXT: mov w8, #1024 // =0x400 ; CHECK-NEXT: movk w8, #33, lsl #16 ; CHECK-NEXT: and w8, w0, w8 ; CHECK-NEXT: cmp w8, #1024 @@ -84,7 +84,7 @@ entry: define i8 @test6(i64 %a) { ; CHECK-LABEL: test6: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #135 +; CHECK-NEXT: mov w8, #135 // =0x87 ; CHECK-NEXT: and x8, x0, x8 ; CHECK-NEXT: cmp x8, #1024 ; CHECK-NEXT: cset w0, eq @@ -101,7 +101,7 @@ entry: define i8 @test7(i64 %a) { ; CHECK-LABEL: test7: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #1024 +; CHECK-NEXT: mov w8, #1024 // =0x400 ; CHECK-NEXT: movk w8, #33, lsl #16 ; CHECK-NEXT: and x8, x0, x8 ; CHECK-NEXT: cmp x8, #1024 @@ -175,7 +175,7 @@ define i32 @test9(ptr nocapture %x, ptr nocapture readonly %y, i32 %n) { ; CHECK-NEXT: cmp w2, #1 ; CHECK-NEXT: b.lt .LBB8_3 ; CHECK-NEXT: // %bb.1: // %for.body.preheader -; CHECK-NEXT: mov w9, #1024 +; CHECK-NEXT: mov w9, #1024 // =0x400 ; CHECK-NEXT: mov w8, w2 ; CHECK-NEXT: movk w9, #32, lsl #16 ; CHECK-NEXT: .LBB8_2: // %for.body @@ -226,7 +226,7 @@ define void @test10(ptr nocapture %x, ptr nocapture readonly %y, ptr nocapture % ; CHECK-LABEL: test10: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: ldr w8, [x1] -; CHECK-NEXT: mov w9, #1024 +; CHECK-NEXT: mov w9, #1024 // =0x400 ; CHECK-NEXT: movk w9, #32, lsl #16 ; CHECK-NEXT: and w8, w8, w9 ; CHECK-NEXT: str w8, [x0] @@ -253,7 +253,7 @@ entry: define i8 @test11(i64 %a) { ; CHECK-LABEL: test11: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #-1610612736 +; CHECK-NEXT: mov w8, #-1610612736 // =0xa0000000 ; CHECK-NEXT: and x8, x0, x8 ; CHECK-NEXT: cmp x8, #1024 ; CHECK-NEXT: cset w0, eq -- GitLab From 0fda758f26c1ec06809fdc067cd65dc146f867d0 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Thu, 28 Mar 2024 01:19:09 +0100 Subject: [PATCH 144/541] [GISEL][NFC] Refactor OperandPredicateMatcher::isHigherPriorityThan (#86837) Fixes #86827 This will simplify code, de-duplicate some logic and fix the faulty bool compare. cc @dcb314 --- .../GlobalISel/GlobalISelMatchTable.cpp | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp index 193f95443b16..19d42b7688da 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp @@ -1077,30 +1077,25 @@ OperandPredicateMatcher::~OperandPredicateMatcher() {} bool OperandPredicateMatcher::isHigherPriorityThan( const OperandPredicateMatcher &B) const { // Generally speaking, an instruction is more important than an Int or a - // LiteralInt because it can cover more nodes but theres an exception to + // LiteralInt because it can cover more nodes but there's an exception to // this. G_CONSTANT's are less important than either of those two because they // are more permissive. - const InstructionOperandMatcher *AOM = - dyn_cast(this); - const InstructionOperandMatcher *BOM = - dyn_cast(&B); + const auto *AOM = dyn_cast(this); + const auto *BOM = dyn_cast(&B); bool AIsConstantInsn = AOM && AOM->getInsnMatcher().isConstantInstruction(); bool BIsConstantInsn = BOM && BOM->getInsnMatcher().isConstantInstruction(); - if (AOM && BOM) { - // The relative priorities between a G_CONSTANT and any other instruction - // don't actually matter but this code is needed to ensure a strict weak - // ordering. This is particularly important on Windows where the rules will - // be incorrectly sorted without it. - if (AIsConstantInsn != BIsConstantInsn) - return AIsConstantInsn < BIsConstantInsn; - return false; - } + // The relative priorities between a G_CONSTANT and any other instruction + // don't actually matter but this code is needed to ensure a strict weak + // ordering. This is particularly important on Windows where the rules will + // be incorrectly sorted without it. + if (AOM && BOM) + return !AIsConstantInsn && BIsConstantInsn; - if (AOM && AIsConstantInsn && (B.Kind == OPM_Int || B.Kind == OPM_LiteralInt)) + if (AIsConstantInsn && (B.Kind == OPM_Int || B.Kind == OPM_LiteralInt)) return false; - if (BOM && BIsConstantInsn && (Kind == OPM_Int || Kind == OPM_LiteralInt)) + if (BIsConstantInsn && (Kind == OPM_Int || Kind == OPM_LiteralInt)) return true; return Kind < B.Kind; -- GitLab From bbfa50696e43f337f55f8bacf739683b181debd5 Mon Sep 17 00:00:00 2001 From: alx32 <103613512+alx32@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:27:51 -0700 Subject: [PATCH 145/541] [lld-macho] Fix bug in makeSyntheticInputSection when -dead_strip flag is specified (#86878) Previously, `makeSyntheticInputSection` would create a new `ConcatInputSection` without setting `live` explicitly for it. Without `-dead_strip` this would be OK since `live` would default to `true`. However, with `-dead_strip`, `live` would default to false, and it would remain set to `false`. This hasn't resulted in any issues so far since no code paths that exposed this issue were present. However a recent change - ObjC relative method lists (https://github.com/llvm/llvm-project/pull/86231) exposes this issue by creating relocations to the `SyntheticInputSection`. When these relocations are attempted to be written, this ends up with a crash(assert), since the `SyntheticInputSection` they refer to is marked as dead (`live` = `false`). With this change, we set the correct behavior - `live` will always be `true`. We add a test case that before this change would trigger an assert in the linker. --- lld/MachO/ConcatOutputSection.cpp | 6 +----- lld/MachO/InputSection.cpp | 3 +++ lld/MachO/InputSection.h | 1 + lld/MachO/SymbolTable.cpp | 2 +- lld/MachO/SyntheticSections.cpp | 2 +- lld/MachO/Writer.cpp | 4 +--- lld/test/MachO/objc-relative-method-lists-simple.s | 4 ++++ 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp index c5c0c8a89e28..279423720be9 100644 --- a/lld/MachO/ConcatOutputSection.cpp +++ b/lld/MachO/ConcatOutputSection.cpp @@ -323,11 +323,7 @@ void TextOutputSection::finalize() { thunkInfo.isec = makeSyntheticInputSection(isec->getSegName(), isec->getName()); thunkInfo.isec->parent = this; - - // This code runs after dead code removal. Need to set the `live` bit - // on the thunk isec so that asserts that check that only live sections - // get written are happy. - thunkInfo.isec->live = true; + assert(thunkInfo.isec->live); StringRef thunkName = saver().save(funcSym->getName() + ".thunk." + std::to_string(thunkInfo.sequence++)); diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp index e3d7a400e4ce..5c1e07cd21b1 100644 --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -281,6 +281,9 @@ ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName, Section §ion = *make
(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0); auto isec = make(section, data, align); + // Since this is an explicitly created 'fake' input section, + // it should not be dead stripped. + isec->live = true; section.subsections.push_back({0, isec}); return isec; } diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h index a0e6afef92cb..0f389e50425a 100644 --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -149,6 +149,7 @@ public: }; // Initialize a fake InputSection that does not belong to any InputFile. +// The created ConcatInputSection will always have 'live=true' ConcatInputSection *makeSyntheticInputSection(StringRef segName, StringRef sectName, uint32_t flags = 0, diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp index 825242f2cc72..755ff270e2f7 100644 --- a/lld/MachO/SymbolTable.cpp +++ b/lld/MachO/SymbolTable.cpp @@ -377,7 +377,7 @@ static void handleSectionBoundarySymbol(const Undefined &sym, StringRef segSect, // live. Marking the isec live ensures an OutputSection is created that the // start/end symbol can refer to. assert(sym.isLive()); - isec->live = true; + assert(isec->live); // This runs after gatherInputSections(), so need to explicitly set parent // and add to inputSections. diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 808ea8eac6eb..6f6b66118b7a 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -850,7 +850,7 @@ ConcatInputSection *ObjCSelRefsHelper::makeSelRef(StringRef methname) { S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP, ArrayRef{selrefData, wordSize}, /*align=*/wordSize); - objcSelref->live = true; + assert(objcSelref->live); objcSelref->relocs.push_back({/*type=*/target->unsignedRelocType, /*pcrel=*/false, /*length=*/3, /*offset=*/0, diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index fe989de648d7..1c054912551e 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -1375,9 +1375,7 @@ void macho::createSyntheticSections() { segment_names::data, section_names::data, S_REGULAR, ArrayRef{arr, target->wordSize}, /*align=*/target->wordSize); - // References from dyld are not visible to us, so ensure this section is - // always treated as live. - in.imageLoaderCache->live = true; + assert(in.imageLoaderCache->live); } OutputSection *macho::firstTLVDataSection = nullptr; diff --git a/lld/test/MachO/objc-relative-method-lists-simple.s b/lld/test/MachO/objc-relative-method-lists-simple.s index 1ffec3c6241c..5a77085c7d93 100644 --- a/lld/test/MachO/objc-relative-method-lists-simple.s +++ b/lld/test/MachO/objc-relative-method-lists-simple.s @@ -8,6 +8,10 @@ # RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists # RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL +## Test arm64 + relative method lists + dead-strip +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists -dead_strip +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL + ## Test arm64 + traditional method lists (no relative offsets) # RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -no_objc_relative_method_lists # RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_NO_REL -- GitLab From cb898e26f3321e0b861609f5fec7f7410e5b6778 Mon Sep 17 00:00:00 2001 From: Kai Sasaki Date: Thu, 28 Mar 2024 09:40:17 +0900 Subject: [PATCH 146/541] [mlir] Make the print function in CRunnerUtil platform agnostic (#86767) The platform running on Apple Silicon does not seem to support the negative nan. It causes the test failure where we explicitly specify the negative nan bit pattern and check the output printed by the CRunnerUtil function. We can make the print function in the utility platform agnostic by using the standard library functions (i.e. `std::isnan` and `std::signbit`) so that we can run the test across platforms that do not support the negative bit pattern. I have added two test cases that would fail in the Apple Silicon platform without print function changes. ``` $ uname -a Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000 arm64 ``` See: https://discourse.llvm.org/t/test-failure-of-sparse-sign-test-in-apple-silicon/77876/3 --- mlir/lib/ExecutionEngine/CRunnerUtils.cpp | 16 ++++++++++++++-- .../test-expand-math-approx.mlir | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp index 48e4b8cd88b5..41c619566b55 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -51,8 +51,20 @@ void stdSort(uint64_t n, V *p) { // details of our vectors. Also useful for direct LLVM IR output. extern "C" void printI64(int64_t i) { fprintf(stdout, "%" PRId64, i); } extern "C" void printU64(uint64_t u) { fprintf(stdout, "%" PRIu64, u); } -extern "C" void printF32(float f) { fprintf(stdout, "%g", f); } -extern "C" void printF64(double d) { fprintf(stdout, "%lg", d); } +extern "C" void printF32(float f) { + if (std::isnan(f) && std::signbit(f)) { + fprintf(stdout, "-nan"); + } else { + fprintf(stdout, "%g", f); + } +} +extern "C" void printF64(double d) { + if (std::isnan(d) && std::signbit(d)) { + fprintf(stdout, "-nan"); + } else { + fprintf(stdout, "%lg", d); + } +} extern "C" void printString(char const *s) { fputs(s, stdout); } extern "C" void printOpen() { fputs("( ", stdout); } extern "C" void printClose() { fputs(" )", stdout); } diff --git a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir index e2229a392bbf..340ef30bf59c 100644 --- a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir +++ b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir @@ -190,6 +190,12 @@ func.func @func_powff64(%a : f64, %b : f64) { return } +func.func @func_powff32(%a : f32, %b : f32) { + %r = math.powf %a, %b : f32 + vector.print %r : f32 + return +} + func.func @powf() { // CHECK-NEXT: 16 %a = arith.constant 4.0 : f64 @@ -230,7 +236,17 @@ func.func @powf() { %j = arith.constant 29385.0 : f64 %j_p = arith.constant 23598.0 : f64 call @func_powff64(%j, %j_p) : (f64, f64) -> () - return + + // CHECK-NEXT: -nan + %k = arith.constant 1.0 : f64 + %k_p = arith.constant 0xfff0000001000000 : f64 + call @func_powff64(%k, %k_p) : (f64, f64) -> () + + // CHECK-NEXT: -nan + %l = arith.constant 1.0 : f32 + %l_p = arith.constant 0xffffffff : f32 + call @func_powff32(%l, %l_p) : (f32, f32) -> () + return } // -------------------------------------------------------------------------- // -- GitLab From 17ab9e64464f989b3fe4a304a450581a618097a0 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 27 Mar 2024 17:44:49 -0700 Subject: [PATCH 147/541] [TSAN] Move test into Linux/ Linux specific test was introduced by #86537 --- compiler-rt/test/tsan/{ => Linux}/signal_in_futex_wait.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename compiler-rt/test/tsan/{ => Linux}/signal_in_futex_wait.cpp (99%) diff --git a/compiler-rt/test/tsan/signal_in_futex_wait.cpp b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp similarity index 99% rename from compiler-rt/test/tsan/signal_in_futex_wait.cpp rename to compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp index cf31e5467486..34d058edd526 100644 --- a/compiler-rt/test/tsan/signal_in_futex_wait.cpp +++ b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp @@ -1,6 +1,6 @@ // RUN: %clang_tsan %s -lstdc++ -o %t && %run %t 2>&1 | FileCheck %s -#include "test.h" +#include "../test.h" #include #include #include -- GitLab From 64f0410193490167aee186abf4de06b681476a86 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Thu, 28 Mar 2024 02:03:24 +0100 Subject: [PATCH 148/541] [CI] Hotfix: CI runs failing due to target escaping (#86897) My patch #86877 contains a mistake. Should have read the comment. Recent buildkite runs fail because of this, so it is a bit urgent. --- .ci/monolithic-linux.sh | 2 +- .ci/monolithic-windows.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 35f1aacb4985..b347c443da67 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -54,4 +54,4 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" -k 0 "${targets}" +ninja -C "${BUILD_DIR}" -k 0 ${targets} diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index f84c0966704e..4fd88ea81c84 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -62,4 +62,4 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" -k 0 "${targets}" +ninja -C "${BUILD_DIR}" -k 0 ${targets} -- GitLab From cc98ffb6dc6ca3e68fd939558eb8c4ddb1cc03de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Thu, 28 Mar 2024 02:09:20 +0100 Subject: [PATCH 149/541] [tsan][test] Remove some unneded debug comments in a tsan test (#86896) I introduced this test in #86537, let's remove some unneeded debugging comments. This PR was initially also moving the test to linux directory but looks like it's already done by 17ab9e64464f989b3fe4a304a450581a618097a0 . --- compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp index 34d058edd526..3c8804aae3d0 100644 --- a/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp +++ b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp @@ -57,16 +57,13 @@ private: Mutex mutex; void *Thread(void *x) { - // fprintf(stderr, "canova here thread 0\n"); // Waiting for the futex. mutex.lock(); - // fprintf(stderr, "canova here thread 1\n"); // Finished waiting. return nullptr; } static void SigprofHandler(int signal, siginfo_t *info, void *context) { - // fprintf(stderr, "canova here sigprof handler\n"); // Unlock the futex. mutex.unlock(); } -- GitLab From f75eebab887903567906d22e790a3be20a2a6438 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 27 Mar 2024 18:14:04 -0700 Subject: [PATCH 150/541] Revert "[CodeGen][arm64e] Add methods and data members to Address, which are needed to authenticate signed pointers (#86721)" (#86898) This reverts commit d9a685a9dd589486e882b722e513ee7b8c84870c. The commit broke ubsan bots. --- clang/lib/CodeGen/ABIInfoImpl.cpp | 10 +- clang/lib/CodeGen/Address.h | 195 +++-------------- clang/lib/CodeGen/CGAtomic.cpp | 53 +++-- clang/lib/CodeGen/CGBlocks.cpp | 34 ++- clang/lib/CodeGen/CGBlocks.h | 3 +- clang/lib/CodeGen/CGBuilder.h | 234 +++++++-------------- clang/lib/CodeGen/CGBuiltin.cpp | 173 ++++++++------- clang/lib/CodeGen/CGCUDANV.cpp | 19 +- clang/lib/CodeGen/CGCXXABI.cpp | 21 +- clang/lib/CodeGen/CGCXXABI.h | 14 +- clang/lib/CodeGen/CGCall.cpp | 171 +++++++-------- clang/lib/CodeGen/CGCall.h | 1 - clang/lib/CodeGen/CGClass.cpp | 76 +++---- clang/lib/CodeGen/CGCleanup.cpp | 110 ++++++---- clang/lib/CodeGen/CGCleanup.h | 2 +- clang/lib/CodeGen/CGCoroutine.cpp | 4 +- clang/lib/CodeGen/CGDecl.cpp | 28 ++- clang/lib/CodeGen/CGException.cpp | 19 +- clang/lib/CodeGen/CGExpr.cpp | 227 ++++++++++---------- clang/lib/CodeGen/CGExprAgg.cpp | 29 ++- clang/lib/CodeGen/CGExprCXX.cpp | 111 +++++----- clang/lib/CodeGen/CGExprConstant.cpp | 4 +- clang/lib/CodeGen/CGExprScalar.cpp | 23 +- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 8 +- clang/lib/CodeGen/CGObjC.cpp | 43 ++-- clang/lib/CodeGen/CGObjCGNU.cpp | 42 ++-- clang/lib/CodeGen/CGObjCMac.cpp | 95 +++++---- clang/lib/CodeGen/CGObjCRuntime.cpp | 6 +- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 194 ++++++++--------- clang/lib/CodeGen/CGOpenMPRuntime.h | 5 +- clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 76 ++++--- clang/lib/CodeGen/CGStmt.cpp | 8 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 87 ++++---- clang/lib/CodeGen/CGVTables.cpp | 9 +- clang/lib/CodeGen/CGValue.h | 250 +++++++++++----------- clang/lib/CodeGen/CodeGenFunction.cpp | 71 +++---- clang/lib/CodeGen/CodeGenFunction.h | 257 +++++++---------------- clang/lib/CodeGen/CodeGenModule.cpp | 2 +- clang/lib/CodeGen/CodeGenPGO.cpp | 10 +- clang/lib/CodeGen/CodeGenPGO.h | 6 +- clang/lib/CodeGen/ItaniumCXXABI.cpp | 52 +++-- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 58 +++-- clang/lib/CodeGen/TargetInfo.h | 5 - clang/lib/CodeGen/Targets/NVPTX.cpp | 2 +- clang/lib/CodeGen/Targets/PPC.cpp | 11 +- clang/lib/CodeGen/Targets/Sparc.cpp | 2 +- clang/lib/CodeGen/Targets/SystemZ.cpp | 9 +- clang/lib/CodeGen/Targets/XCore.cpp | 2 +- clang/utils/TableGen/MveEmitter.cpp | 2 +- llvm/include/llvm/IR/IRBuilder.h | 1 - 50 files changed, 1234 insertions(+), 1640 deletions(-) diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 3e34d82cb399..dd59101ecc81 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -187,7 +187,7 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits FullDirectSize = DirectSize.alignTo(SlotSize); Address NextPtr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next"); - CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); + CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr); // If the argument is smaller than a slot, and this is a big-endian // target, the argument will be right-adjusted in its slot. @@ -239,8 +239,8 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, const llvm::Twine &Name) { assert(Addr1.getType() == Addr2.getType()); llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name); - PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1); - PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2); + PHI->addIncoming(Addr1.getPointer(), Block1); + PHI->addIncoming(Addr2.getPointer(), Block2); CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment()); return Address(PHI, Addr1.getElementType(), Align); } @@ -400,7 +400,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty); llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy); llvm::Value *Addr = - CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy); + CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy); return Address(Addr, ElementTy, TyAlignForABI); } else { assert((AI.isDirect() || AI.isExtend()) && @@ -416,7 +416,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!"); Address Temp = CGF.CreateMemTemp(Ty, "varet"); - Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), + Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(), CGF.ConvertTypeForMem(Ty)); CGF.Builder.CreateStore(Val, Temp); return Temp; diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index 35ec370a139c..cf48df8f5e73 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #include "clang/AST/CharUnits.h" -#include "clang/AST/Type.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Constants.h" #include "llvm/Support/MathExtras.h" @@ -23,41 +22,28 @@ namespace clang { namespace CodeGen { -class Address; -class CGBuilderTy; -class CodeGenFunction; -class CodeGenModule; - // Indicates whether a pointer is known not to be null. enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; -/// An abstract representation of an aligned address. This is designed to be an -/// IR-level abstraction, carrying just the information necessary to perform IR -/// operations on an address like loads and stores. In particular, it doesn't -/// carry C type information or allow the representation of things like -/// bit-fields; clients working at that level should generally be using -/// `LValue`. -/// The pointer contained in this class is known to be unsigned. -class RawAddress { +/// An aligned address. +class Address { llvm::PointerIntPair PointerAndKnownNonNull; llvm::Type *ElementType; CharUnits Alignment; protected: - RawAddress(std::nullptr_t) : ElementType(nullptr) {} + Address(std::nullptr_t) : ElementType(nullptr) {} public: - RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, - KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) : PointerAndKnownNonNull(Pointer, IsKnownNonNull), ElementType(ElementType), Alignment(Alignment) { assert(Pointer != nullptr && "Pointer cannot be null"); assert(ElementType != nullptr && "Element type cannot be null"); } - inline RawAddress(Address Addr); - - static RawAddress invalid() { return RawAddress(nullptr); } + static Address invalid() { return Address(nullptr); } bool isValid() const { return PointerAndKnownNonNull.getPointer() != nullptr; } @@ -94,133 +80,6 @@ public: return Alignment; } - /// Return address with different element type, but same pointer and - /// alignment. - RawAddress withElementType(llvm::Type *ElemTy) const { - return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); - } - - KnownNonNull_t isKnownNonNull() const { - assert(isValid()); - return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); - } -}; - -/// Like RawAddress, an abstract representation of an aligned address, but the -/// pointer contained in this class is possibly signed. -class Address { - friend class CGBuilderTy; - - // The boolean flag indicates whether the pointer is known to be non-null. - llvm::PointerIntPair Pointer; - - /// The expected IR type of the pointer. Carrying accurate element type - /// information in Address makes it more convenient to work with Address - /// values and allows frontend assertions to catch simple mistakes. - llvm::Type *ElementType = nullptr; - - CharUnits Alignment; - - /// Offset from the base pointer. - llvm::Value *Offset = nullptr; - - llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const; - -protected: - Address(std::nullptr_t) : ElementType(nullptr) {} - -public: - Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment, - KnownNonNull_t IsKnownNonNull = NotKnownNonNull) - : Pointer(pointer, IsKnownNonNull), ElementType(elementType), - Alignment(alignment) { - assert(pointer != nullptr && "Pointer cannot be null"); - assert(elementType != nullptr && "Element type cannot be null"); - assert(!alignment.isZero() && "Alignment cannot be zero"); - } - - Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment, - llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) - : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType), - Alignment(Alignment), Offset(Offset) {} - - Address(RawAddress RawAddr) - : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr), - ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr), - Alignment(RawAddr.isValid() ? RawAddr.getAlignment() - : CharUnits::Zero()) {} - - static Address invalid() { return Address(nullptr); } - bool isValid() const { return Pointer.getPointer() != nullptr; } - - /// This function is used in situations where the caller is doing some sort of - /// opaque "laundering" of the pointer. - void replaceBasePointer(llvm::Value *P) { - assert(isValid() && "pointer isn't valid"); - assert(P->getType() == Pointer.getPointer()->getType() && - "Pointer's type changed"); - Pointer.setPointer(P); - assert(isValid() && "pointer is invalid after replacement"); - } - - CharUnits getAlignment() const { return Alignment; } - - void setAlignment(CharUnits Value) { Alignment = Value; } - - llvm::Value *getBasePointer() const { - assert(isValid() && "pointer isn't valid"); - return Pointer.getPointer(); - } - - /// Return the type of the pointer value. - llvm::PointerType *getType() const { - return llvm::PointerType::get( - ElementType, - llvm::cast(Pointer.getPointer()->getType()) - ->getAddressSpace()); - } - - /// Return the type of the values stored in this address. - llvm::Type *getElementType() const { - assert(isValid()); - return ElementType; - } - - /// Return the address space that this address resides in. - unsigned getAddressSpace() const { return getType()->getAddressSpace(); } - - /// Return the IR name of the pointer value. - llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } - - // This function is called only in CGBuilderBaseTy::CreateElementBitCast. - void setElementType(llvm::Type *Ty) { - assert(hasOffset() && - "this funcion shouldn't be called when there is no offset"); - ElementType = Ty; - } - - /// Whether the pointer is known not to be null. - KnownNonNull_t isKnownNonNull() const { - assert(isValid()); - return (KnownNonNull_t)Pointer.getInt(); - } - - Address setKnownNonNull() { - assert(isValid()); - Pointer.setInt(KnownNonNull); - return *this; - } - - bool hasOffset() const { return Offset; } - - llvm::Value *getOffset() const { return Offset; } - - /// Return the pointer contained in this class after authenticating it and - /// adding offset to it if necessary. - llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - return getBasePointer(); - } - /// Return address with different pointer, but same element type and /// alignment. Address withPointer(llvm::Value *NewPointer, @@ -232,59 +91,61 @@ public: /// Return address with different alignment, but same pointer and element /// type. Address withAlignment(CharUnits NewAlignment) const { - return Address(Pointer.getPointer(), getElementType(), NewAlignment, + return Address(getPointer(), getElementType(), NewAlignment, isKnownNonNull()); } /// Return address with different element type, but same pointer and /// alignment. Address withElementType(llvm::Type *ElemTy) const { - if (!hasOffset()) - return Address(getBasePointer(), ElemTy, getAlignment(), nullptr, - isKnownNonNull()); - Address A(*this); - A.ElementType = ElemTy; - return A; + return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); } -}; -inline RawAddress::RawAddress(Address Addr) - : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, - Addr.isValid() ? Addr.isKnownNonNull() - : NotKnownNonNull), - ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), - Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} + /// Whether the pointer is known not to be null. + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); + } + + /// Set the non-null bit. + Address setKnownNonNull() { + assert(isValid()); + PointerAndKnownNonNull.setInt(true); + return *this; + } +}; /// A specialization of Address that requires the address to be an /// LLVM Constant. -class ConstantAddress : public RawAddress { - ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {} +class ConstantAddress : public Address { + ConstantAddress(std::nullptr_t) : Address(nullptr) {} public: ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, CharUnits alignment) - : RawAddress(pointer, elementType, alignment) {} + : Address(pointer, elementType, alignment) {} static ConstantAddress invalid() { return ConstantAddress(nullptr); } llvm::Constant *getPointer() const { - return llvm::cast(RawAddress::getPointer()); + return llvm::cast(Address::getPointer()); } ConstantAddress withElementType(llvm::Type *ElemTy) const { return ConstantAddress(getPointer(), ElemTy, getAlignment()); } - static bool isaImpl(RawAddress addr) { + static bool isaImpl(Address addr) { return llvm::isa(addr.getPointer()); } - static ConstantAddress castImpl(RawAddress addr) { + static ConstantAddress castImpl(Address addr) { return ConstantAddress(llvm::cast(addr.getPointer()), addr.getElementType(), addr.getAlignment()); } }; + } // Present a minimal LLVM-like casting interface. diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index 56198385de9d..fb03d013e8af 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -80,7 +80,7 @@ namespace { AtomicSizeInBits = C.toBits( C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1) .alignTo(lvalue.getAlignment())); - llvm::Value *BitFieldPtr = lvalue.getRawBitFieldPointer(CGF); + llvm::Value *BitFieldPtr = lvalue.getBitFieldPointer(); auto OffsetInChars = (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) * lvalue.getAlignment(); @@ -139,13 +139,13 @@ namespace { const LValue &getAtomicLValue() const { return LVal; } llvm::Value *getAtomicPointer() const { if (LVal.isSimple()) - return LVal.emitRawPointer(CGF); + return LVal.getPointer(CGF); else if (LVal.isBitField()) - return LVal.getRawBitFieldPointer(CGF); + return LVal.getBitFieldPointer(); else if (LVal.isVectorElt()) - return LVal.getRawVectorPointer(CGF); + return LVal.getVectorPointer(); assert(LVal.isExtVectorElt()); - return LVal.getRawExtVectorPointer(CGF); + return LVal.getExtVectorPointer(); } Address getAtomicAddress() const { llvm::Type *ElTy; @@ -368,7 +368,7 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const { return false; CGF.Builder.CreateMemSet( - addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0), + addr.getPointer(), llvm::ConstantInt::get(CGF.Int8Ty, 0), CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(), LVal.getAlignment().getAsAlign()); return true; @@ -1055,8 +1055,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { return getTargetHooks().performAddrSpaceCast( *this, V, AS, LangAS::opencl_generic, DestType, false); }; - - Args.add(RValue::get(CastToGenericAddrSpace(Ptr.emitRawPointer(*this), + Args.add(RValue::get(CastToGenericAddrSpace(Ptr.getPointer(), E->getPtr()->getType())), getContext().VoidPtrTy); @@ -1087,10 +1086,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_compare_exchange"; RetTy = getContext().BoolTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), E->getVal1()->getType())), getContext().VoidPtrTy); - Args.add(RValue::get(CastToGenericAddrSpace(Val2.emitRawPointer(*this), + Args.add(RValue::get(CastToGenericAddrSpace(Val2.getPointer(), E->getVal2()->getType())), getContext().VoidPtrTy); Args.add(RValue::get(Order), getContext().IntTy); @@ -1106,7 +1105,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__scoped_atomic_exchange: case AtomicExpr::AO__scoped_atomic_exchange_n: LibCallName = "__atomic_exchange"; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1121,7 +1120,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_store"; RetTy = getContext().VoidTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1200,8 +1199,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { if (!HaveRetTy) { // Value is returned through parameter before the order. RetTy = getContext().VoidTy; - Args.add(RValue::get( - CastToGenericAddrSpace(Dest.emitRawPointer(*this), RetTy)), + Args.add(RValue::get(CastToGenericAddrSpace(Dest.getPointer(), RetTy)), getContext().VoidPtrTy); } // Order is always the last parameter. @@ -1515,7 +1513,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } else TempAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(TempAddr.emitRawPointer(CGF), AO, IsVolatile); + EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile); // Okay, turn that back into the original value or whole atomic (for // non-simple lvalues) type. @@ -1675,9 +1673,9 @@ std::pair AtomicInfo::EmitAtomicCompareExchange( if (shouldUseLibcall()) { // Produce a source address. Address ExpectedAddr = materializeRValue(Expected); - llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); - llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF); - auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, + Address DesiredAddr = materializeRValue(Desired); + auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), + DesiredAddr.getPointer(), Success, Failure); return std::make_pair( convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(), @@ -1759,7 +1757,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall( Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1773,10 +1771,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall( AggValueSlot::ignored(), SourceLocation(), /*AsValue=*/false); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr); - llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); - llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), + DesiredAddr.getPointer(), + AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1845,7 +1843,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1856,10 +1854,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, CGF.Builder.CreateStore(OldVal, DesiredAddr); } EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr); - llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); - llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), + DesiredAddr.getPointer(), + AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1959,8 +1957,7 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(atomics.getAtomicPointer()), getContext().VoidPtrTy); - args.add(RValue::get(srcAddr.emitRawPointer(*this)), - getContext().VoidPtrTy); + args.add(RValue::get(srcAddr.getPointer()), getContext().VoidPtrTy); args.add( RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))), getContext().IntTy); diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index a01f2c7c9798..ad0b50d79961 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -36,8 +36,7 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), NoEscape(false), HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), CapturesNonExternalType(false), - LocalAddress(RawAddress::invalid()), StructureType(nullptr), - Block(block) { + LocalAddress(Address::invalid()), StructureType(nullptr), Block(block) { // Skip asm prefix, if any. 'name' is usually taken directly from // the mangled name of the enclosing function. @@ -795,7 +794,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // Otherwise, we have to emit this as a local block. - RawAddress blockAddr = blockInfo.LocalAddress; + Address blockAddr = blockInfo.LocalAddress; assert(blockAddr.isValid() && "block has no address!"); llvm::Constant *isa; @@ -940,7 +939,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { if (CI.isNested()) byrefPointer = Builder.CreateLoad(src, "byref.capture"); else - byrefPointer = src.emitRawPointer(*this); + byrefPointer = src.getPointer(); // Write that void* into the capture field. Builder.CreateStore(byrefPointer, blockField); @@ -962,10 +961,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { } // If it's a reference variable, copy the reference into the block field. - } else if (auto refType = type->getAs()) { - Builder.CreateStore(src.emitRawPointer(*this), blockField); + } else if (type->isReferenceType()) { + Builder.CreateStore(src.getPointer(), blockField); - // If type is const-qualified, copy the value into the block field. + // If type is const-qualified, copy the value into the block field. } else if (type.isConstQualified() && type.getObjCLifetime() == Qualifiers::OCL_Strong && CGM.getCodeGenOpts().OptimizationLevel != 0) { @@ -1378,7 +1377,7 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, // Allocate a stack slot like for any local variable to guarantee optimal // debug info at -O0. The mem2reg pass will eliminate it when optimizing. - RawAddress alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); + Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); Builder.CreateStore(arg, alloc); if (CGDebugInfo *DI = getDebugInfo()) { if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { @@ -1498,7 +1497,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( // frame setup instruction by llvm::DwarfDebug::beginFunction(). auto NL = ApplyDebugLocation::CreateEmpty(*this); Builder.CreateStore(BlockPointer, Alloca); - BlockPointerDbgLoc = Alloca.emitRawPointer(*this); + BlockPointerDbgLoc = Alloca.getPointer(); } // If we have a C++ 'this' reference, go ahead and force it into @@ -1558,8 +1557,8 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); if (capture.isConstant()) { auto addr = LocalDeclMap.find(variable)->second; - (void)DI->EmitDeclareOfAutoVariable( - variable, addr.emitRawPointer(*this), Builder); + (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), + Builder); continue; } @@ -1663,7 +1662,7 @@ struct CallBlockRelease final : EHScopeStack::Cleanup { if (LoadBlockVarAddr) { BlockVarAddr = CGF.Builder.CreateLoad(Addr); } else { - BlockVarAddr = Addr.emitRawPointer(CGF); + BlockVarAddr = Addr.getPointer(); } CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow); @@ -1963,15 +1962,13 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - if (auto *I = - cast_or_null(dstField.getBasePointer())) - I->eraseFromParent(); + cast(dstField.getPointer())->eraseFromParent(); } break; } case BlockCaptureEntityKind::BlockObject: { llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - llvm::Value *dstAddr = dstField.emitRawPointer(*this); + llvm::Value *dstAddr = dstField.getPointer(); llvm::Value *args[] = { dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) }; @@ -2142,7 +2139,7 @@ public: llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign(); - llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal}; + llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal }; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2699,8 +2696,7 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { storeHeaderField(V, getPointerSize(), "byref.isa"); // Store the address of the variable into its own forwarding pointer. - storeHeaderField(addr.emitRawPointer(*this), getPointerSize(), - "byref.forwarding"); + storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding"); // Blocks ABI: // c) the flags field is set to either 0 if no helper functions are diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index 8d10c4f69b20..4ef1ae9f3365 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -271,8 +271,7 @@ public: /// The block's captures. Non-constant captures are sorted by their offsets. llvm::SmallVector SortedCaptures; - // Currently we assume that block-pointer types are never signed. - RawAddress LocalAddress; + Address LocalAddress; llvm::StructType *StructureType; const BlockDecl *Block; const BlockExpr *BlockExpression; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 6dd9da7c4cad..bf5ab171d720 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -10,9 +10,7 @@ #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #include "Address.h" -#include "CGValue.h" #include "CodeGenTypeCache.h" -#include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Type.h" @@ -20,15 +18,12 @@ namespace clang { namespace CodeGen { -class CGBuilderTy; class CodeGenFunction; /// This is an IRBuilder insertion helper that forwards to /// CodeGenFunction::InsertHelper, which adds necessary metadata to /// instructions. class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { - friend CGBuilderTy; - public: CGBuilderInserter() = default; explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} @@ -48,42 +43,10 @@ typedef llvm::IRBuilder CGBuilderBaseTy; class CGBuilderTy : public CGBuilderBaseTy { - friend class Address; - /// Storing a reference to the type cache here makes it a lot easier /// to build natural-feeling, target-specific IR. const CodeGenTypeCache &TypeCache; - CodeGenFunction *getCGF() const { return getInserter().CGF; } - - llvm::Value *emitRawPointerFromAddress(Address Addr) const { - return Addr.getBasePointer(); - } - - template - Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, - const llvm::Twine &Name) { - const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - llvm::GetElementPtrInst *GEP; - if (IsInBounds) - GEP = cast(CreateConstInBoundsGEP2_32( - Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, - Name)); - else - GEP = cast(CreateConstGEP2_32( - Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, - Name)); - llvm::APInt Offset( - DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, - /*isSigned=*/true); - if (!GEP->accumulateConstantOffset(DL, Offset)) - llvm_unreachable("offset of GEP with constants is always computable"); - return Address(GEP, GEP->getResultElementType(), - Addr.getAlignment().alignmentAtOffset( - CharUnits::fromQuantity(Offset.getSExtValue())), - IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull); - } - public: CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) : CGBuilderBaseTy(C), TypeCache(TypeCache) {} @@ -106,22 +69,20 @@ public: // Note that we intentionally hide the CreateLoad APIs that don't // take an alignment. llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), - emitRawPointerFromAddress(Addr), + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { // This overload is required to prevent string literals from // ending up in the IsVolatile overload. - return CreateAlignedLoad(Addr.getElementType(), - emitRawPointerFromAddress(Addr), + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, const llvm::Twine &Name = "") { - return CreateAlignedLoad( - Addr.getElementType(), emitRawPointerFromAddress(Addr), - Addr.getAlignment().getAsAlign(), IsVolatile, Name); + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + Addr.getAlignment().getAsAlign(), IsVolatile, + Name); } using CGBuilderBaseTy::CreateAlignedLoad; @@ -135,7 +96,7 @@ public: // take an alignment. llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile = false) { - return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr), + return CreateAlignedStore(Val, Addr.getPointer(), Addr.getAlignment().getAsAlign(), IsVolatile); } @@ -171,41 +132,33 @@ public: llvm::AtomicOrdering FailureOrdering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { return CGBuilderBaseTy::CreateAtomicCmpXchg( - Addr.emitRawPointer(*getCGF()), Cmp, New, - Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering, - SSID); + Addr.getPointer(), Cmp, New, Addr.getAlignment().getAsAlign(), + SuccessOrdering, FailureOrdering, SSID); } llvm::AtomicRMWInst * CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Ordering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { - return CGBuilderBaseTy::CreateAtomicRMW( - Op, Addr.emitRawPointer(*getCGF()), Val, - Addr.getAlignment().getAsAlign(), Ordering, SSID); + return CGBuilderBaseTy::CreateAtomicRMW(Op, Addr.getPointer(), Val, + Addr.getAlignment().getAsAlign(), + Ordering, SSID); } using CGBuilderBaseTy::CreateAddrSpaceCast; Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, - llvm::Type *ElementTy, const llvm::Twine &Name = "") { - if (!Addr.hasOffset()) - return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), - ElementTy, Addr.getAlignment(), nullptr, - Addr.isKnownNonNull()); - // Eagerly force a raw address if these is an offset. - return RawAddress( - CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), - ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); + return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), + Addr.isKnownNonNull()); } using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name = "") { - if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace()) - return Addr.withElementType(ElementTy); - return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name); + llvm::Value *Ptr = + CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); + return Address(Ptr, ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); } /// Given @@ -223,11 +176,10 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), - Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + return Address( + CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); } /// Given @@ -246,7 +198,7 @@ public: CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), {getSize(CharUnits::Zero()), getSize(Index)}, Name), ElTy->getElementType(), Addr.getAlignment().alignmentAtOffset(Index * EltSize), @@ -264,10 +216,10 @@ public: const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address( - CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -277,133 +229,110 @@ public: /// where i64 is actually the target word size. Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name = "") { - llvm::Type *ElTy = Addr.getElementType(); const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); + CharUnits EltSize = + CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); - return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), + return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Index), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize)); + Addr.getAlignment().alignmentAtOffset(Index * EltSize), + NotKnownNonNull); } /// Create GEP with single dynamic index. The address alignment is reduced /// according to the element size. using CGBuilderBaseTy::CreateGEP; - Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, + Address CreateGEP(Address Addr, llvm::Value *Index, const llvm::Twine &Name = "") { const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); return Address( - CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name), + CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), Addr.getElementType(), - Addr.getAlignment().alignmentOfArrayElement(EltSize)); + Addr.getAlignment().alignmentOfArrayElement(EltSize), NotKnownNonNull); } /// Given a pointer to i8, adjust it by a given constant offset. Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), - getSize(Offset), Name), - Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Offset), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } - Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), + return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), getSize(Offset), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset)); + Addr.getAlignment().alignmentAtOffset(Offset), + NotKnownNonNull); } using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name = "") { - return createConstGEP2_32(Addr, Idx0, Idx1, Name); - } - - using CGBuilderBaseTy::CreateConstGEP2_32; - Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, - const llvm::Twine &Name = "") { - return createConstGEP2_32(Addr, Idx0, Idx1, Name); - } - - Address CreateGEP(Address Addr, ArrayRef IdxList, - llvm::Type *ElementType, CharUnits Align, - const Twine &Name = "") { - llvm::Value *Ptr = emitRawPointerFromAddress(Addr); - return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name), - ElementType, Align); - } - - using CGBuilderBaseTy::CreateInBoundsGEP; - Address CreateInBoundsGEP(Address Addr, ArrayRef IdxList, - llvm::Type *ElementType, CharUnits Align, - const Twine &Name = "") { - return RawAddress(CreateInBoundsGEP(Addr.getElementType(), - emitRawPointerFromAddress(Addr), - IdxList, Name), - ElementType, Align, Addr.isKnownNonNull()); - } + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - using CGBuilderBaseTy::CreateIsNull; - llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") { - if (!Addr.hasOffset()) - return CreateIsNull(Addr.getBasePointer(), Name); - // The pointer isn't null if Addr has an offset since offsets can always - // be applied inbound. - return llvm::ConstantInt::getFalse(Context); + auto *GEP = cast(CreateConstInBoundsGEP2_32( + Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); + llvm::APInt Offset( + DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, + /*isSigned=*/true); + if (!GEP->accumulateConstantOffset(DL, Offset)) + llvm_unreachable("offset of GEP with constants is always computable"); + return Address(GEP, GEP->getResultElementType(), + Addr.getAlignment().alignmentAtOffset( + CharUnits::fromQuantity(Offset.getSExtValue())), + Addr.isKnownNonNull()); } using CGBuilderBaseTy::CreateMemCpy; llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); - llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); - return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, - Src.getAlignment().getAsAlign(), Size, IsVolatile); + return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), + Src.getPointer(), Src.getAlignment().getAsAlign(), Size, + IsVolatile); } llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, bool IsVolatile = false) { - llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); - llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); - return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, - Src.getAlignment().getAsAlign(), Size, IsVolatile); + return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), + Src.getPointer(), Src.getAlignment().getAsAlign(), Size, + IsVolatile); } using CGBuilderBaseTy::CreateMemCpyInline; llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { - llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); - llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); - return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, - Src.getAlignment().getAsAlign(), getInt64(Size)); + return CreateMemCpyInline( + Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), + Src.getAlignment().getAsAlign(), getInt64(Size)); } using CGBuilderBaseTy::CreateMemMove; llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); - llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); - return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, - Src.getAlignment().getAsAlign(), Size, IsVolatile); + return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), + Src.getPointer(), Src.getAlignment().getAsAlign(), + Size, IsVolatile); } using CGBuilderBaseTy::CreateMemSet; llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size, + return CreateMemSet(Dest.getPointer(), Value, Size, Dest.getAlignment().getAsAlign(), IsVolatile); } using CGBuilderBaseTy::CreateMemSetInline; llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, uint64_t Size) { - return CreateMemSetInline(emitRawPointerFromAddress(Dest), + return CreateMemSetInline(Dest.getPointer(), Dest.getAlignment().getAsAlign(), Value, getInt64(Size)); } @@ -417,31 +346,16 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address( - CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr), - Index, FieldIndex, DbgInfo), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset)); - } - - using CGBuilderBaseTy::CreatePreserveUnionAccessIndex; - Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex, - llvm::MDNode *DbgInfo) { - Addr.replaceBasePointer(CreatePreserveUnionAccessIndex( - Addr.getBasePointer(), FieldIndex, DbgInfo)); - return Addr; + return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), + Index, FieldIndex, DbgInfo), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); } using CGBuilderBaseTy::CreateLaunderInvariantGroup; Address CreateLaunderInvariantGroup(Address Addr) { - Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer())); - return Addr; - } - - using CGBuilderBaseTy::CreateStripInvariantGroup; - Address CreateStripInvariantGroup(Address Addr) { - Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer())); - return Addr; + return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()), + Addr.isKnownNonNull()); } }; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 5ab5917c0c8d..fdb517eb254d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2117,9 +2117,9 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( auto AL = ApplyDebugLocation::CreateArtificial(*this); CharUnits Offset; - Address BufAddr = makeNaturalAddressForPointer( - Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Ctx.VoidTy, - BufferAlignment); + Address BufAddr = + Address(Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Int8Ty, + BufferAlignment); Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()), @@ -2162,7 +2162,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { // Ignore argument 1, the format string. It is not currently used. CallArgList Args; - Args.add(RValue::get(BufAddr.emitRawPointer(*this)), Ctx.VoidPtrTy); + Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy); for (const auto &Item : Layout.Items) { int Size = Item.getSizeByte(); @@ -2202,8 +2202,8 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { if (!isa(ArgVal)) { CleanupKind Cleanup = getARCCleanupKind(); QualType Ty = TheExpr->getType(); - RawAddress Alloca = RawAddress::invalid(); - RawAddress Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); + Address Alloca = Address::invalid(); + Address Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); ArgVal = EmitARCRetain(Ty, ArgVal); Builder.CreateStore(ArgVal, Addr); pushLifetimeExtendedDestroy(Cleanup, Alloca, Ty, @@ -2236,7 +2236,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( Layout, BufAddr.getAlignment()); EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); - return RValue::get(BufAddr, *this); + return RValue::get(BufAddr.getPointer()); } static bool isSpecialUnsignedMultiplySignedResult( @@ -2984,7 +2984,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Check NonnullAttribute/NullabilityArg and Alignment. auto EmitArgCheck = [&](TypeCheckKind Kind, Address A, const Expr *Arg, unsigned ParmNum) { - Value *Val = A.emitRawPointer(*this); + Value *Val = A.getPointer(); EmitNonNullArgCheck(RValue::get(Val), Arg->getType(), Arg->getExprLoc(), FD, ParmNum); @@ -3013,12 +3013,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_va_end: EmitVAStartEnd(BuiltinID == Builtin::BI__va_start ? EmitScalarExpr(E->getArg(0)) - : EmitVAListRef(E->getArg(0)).emitRawPointer(*this), + : EmitVAListRef(E->getArg(0)).getPointer(), BuiltinID != Builtin::BI__builtin_va_end); return RValue::get(nullptr); case Builtin::BI__builtin_va_copy: { - Value *DstPtr = EmitVAListRef(E->getArg(0)).emitRawPointer(*this); - Value *SrcPtr = EmitVAListRef(E->getArg(1)).emitRawPointer(*this); + Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer(); + Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer(); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy, {DstPtr->getType()}), {DstPtr, SrcPtr}); return RValue::get(nullptr); @@ -3849,13 +3849,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); Address Src = EmitPointerWithAlignment(E->getArg(0)); - EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), - E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, - 0); + EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); Value *Result = MB.CreateColumnMajorLoad( - Src.getElementType(), Src.emitRawPointer(*this), + Src.getElementType(), Src.getPointer(), Align(Src.getAlignment().getQuantity()), Stride, IsVolatile, - ResultTy->getNumRows(), ResultTy->getNumColumns(), "matrix"); + ResultTy->getNumRows(), ResultTy->getNumColumns(), + "matrix"); return RValue::get(Result); } @@ -3870,13 +3870,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, assert(PtrTy && "arg1 must be of pointer type"); bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); - EmitNonNullArgCheck(RValue::get(Dst.emitRawPointer(*this)), - E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, - 0); + EmitNonNullArgCheck(RValue::get(Dst.getPointer()), E->getArg(1)->getType(), + E->getArg(1)->getExprLoc(), FD, 0); Value *Result = MB.CreateColumnMajorStore( - Matrix, Dst.emitRawPointer(*this), - Align(Dst.getAlignment().getQuantity()), Stride, IsVolatile, - MatrixTy->getNumRows(), MatrixTy->getNumColumns()); + Matrix, Dst.getPointer(), Align(Dst.getAlignment().getQuantity()), + Stride, IsVolatile, MatrixTy->getNumRows(), MatrixTy->getNumColumns()); return RValue::get(Result); } @@ -4035,7 +4033,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_bzero: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); Value *SizeVal = EmitScalarExpr(E->getArg(1)); - EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), + EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false); return RValue::get(nullptr); @@ -4046,12 +4044,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), - E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, - 0); - EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), - E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, - 0); + EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(1)->getType(), + E->getArg(1)->getExprLoc(), FD, 0); Builder.CreateMemMove(Dest, Src, SizeVal, false); return RValue::get(nullptr); } @@ -4068,10 +4064,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateMemCpy(Dest, Src, SizeVal, false); if (BuiltinID == Builtin::BImempcpy || BuiltinID == Builtin::BI__builtin_mempcpy) - return RValue::get(Builder.CreateInBoundsGEP( - Dest.getElementType(), Dest.emitRawPointer(*this), SizeVal)); + return RValue::get(Builder.CreateInBoundsGEP(Dest.getElementType(), + Dest.getPointer(), SizeVal)); else - return RValue::get(Dest, *this); + return RValue::get(Dest.getPointer()); } case Builtin::BI__builtin_memcpy_inline: { @@ -4103,7 +4099,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest, *this); + return RValue::get(Dest.getPointer()); } case Builtin::BI__builtin_objc_memmove_collectable: { @@ -4112,7 +4108,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *SizeVal = EmitScalarExpr(E->getArg(2)); CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestAddr, SrcAddr, SizeVal); - return RValue::get(DestAddr, *this); + return RValue::get(DestAddr.getPointer()); } case Builtin::BI__builtin___memmove_chk: { @@ -4129,7 +4125,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest, *this); + return RValue::get(Dest.getPointer()); } case Builtin::BImemmove: @@ -4140,7 +4136,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitArgCheck(TCK_Store, Dest, E->getArg(0), 0); EmitArgCheck(TCK_Load, Src, E->getArg(1), 1); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest, *this); + return RValue::get(Dest.getPointer()); } case Builtin::BImemset: case Builtin::BI__builtin_memset: { @@ -4148,10 +4144,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), + EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest, *this); + return RValue::get(Dest.getPointer()); } case Builtin::BI__builtin_memset_inline: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); @@ -4159,9 +4155,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); uint64_t Size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); - EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), - E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, - 0); + EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSetInline(Dest, ByteVal, Size); return RValue::get(nullptr); } @@ -4180,7 +4175,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.getInt8Ty()); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest, *this); + return RValue::get(Dest.getPointer()); } case Builtin::BI__builtin_wmemchr: { // The MSVC runtime library does not provide a definition of wmemchr, so we @@ -4402,14 +4397,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Store the stack pointer to the setjmp buffer. Value *StackAddr = Builder.CreateStackSave(); - assert(Buf.emitRawPointer(*this)->getType() == StackAddr->getType()); + assert(Buf.getPointer()->getType() == StackAddr->getType()); Address StackSaveSlot = Builder.CreateConstInBoundsGEP(Buf, 2); Builder.CreateStore(StackAddr, StackSaveSlot); // Call LLVM's EH setjmp, which is lightweight. Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); - return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); + return RValue::get(Builder.CreateCall(F, Buf.getPointer())); } case Builtin::BI__builtin_longjmp: { Value *Buf = EmitScalarExpr(E->getArg(0)); @@ -5582,7 +5577,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(2)); - llvm::Value *Range = NDRangeL.getAddress(*this).emitRawPointer(*this); + llvm::Value *Range = NDRangeL.getAddress(*this).getPointer(); llvm::Type *RangeTy = NDRangeL.getAddress(*this).getType(); if (NumArgs == 4) { @@ -5691,10 +5686,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, getContext(), Expr::NPC_ValueDependentIsNotNull)) { EventWaitList = llvm::ConstantPointerNull::get(PtrTy); } else { - EventWaitList = - E->getArg(4)->getType()->isArrayType() - ? EmitArrayToPointerDecay(E->getArg(4)).emitRawPointer(*this) - : EmitScalarExpr(E->getArg(4)); + EventWaitList = E->getArg(4)->getType()->isArrayType() + ? EmitArrayToPointerDecay(E->getArg(4)).getPointer() + : EmitScalarExpr(E->getArg(4)); // Convert to generic address space. EventWaitList = Builder.CreatePointerCast(EventWaitList, PtrTy); } @@ -5790,7 +5784,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Type *GenericVoidPtrTy = Builder.getPtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); - llvm::Value *NDRange = NDRangeL.getAddress(*this).emitRawPointer(*this); + llvm::Value *NDRange = NDRangeL.getAddress(*this).getPointer(); auto Info = CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); Value *Kernel = @@ -5875,7 +5869,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy0 = FTy->getParamType(0); if (PTy0 != Arg0Val->getType()) { if (Arg0Ty->isArrayType()) - Arg0Val = EmitArrayToPointerDecay(Arg0).emitRawPointer(*this); + Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); else Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); } @@ -5913,7 +5907,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy1 = FTy->getParamType(1); if (PTy1 != Arg1Val->getType()) { if (Arg1Ty->isArrayType()) - Arg1Val = EmitArrayToPointerDecay(Arg1).emitRawPointer(*this); + Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer(); else Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1); } @@ -5927,7 +5921,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_ms_va_start: case Builtin::BI__builtin_ms_va_end: return RValue::get( - EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).emitRawPointer(*this), + EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(), BuiltinID == Builtin::BI__builtin_ms_va_start)); case Builtin::BI__builtin_ms_va_copy: { @@ -5969,8 +5963,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // If this is a predefined lib function (e.g. malloc), emit the call // using exactly the normal call path. if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return emitLibraryCall( - *this, FD, E, cast(EmitScalarExpr(E->getCallee()))); + return emitLibraryCall(*this, FD, E, + cast(EmitScalarExpr(E->getCallee()))); // Check that a call to a target specific builtin has the correct target // features. @@ -6087,7 +6081,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(nullptr); return RValue::get(V); case TEK_Aggregate: - return RValue::getAggregate(ReturnValue.getAddress(), + return RValue::getAggregate(ReturnValue.getValue(), ReturnValue.isVolatile()); case TEK_Complex: llvm_unreachable("No current target builtin returns complex"); @@ -8857,7 +8851,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.emitRawPointer(*this)); + Ops.push_back(PtrOp0.getPointer()); continue; } } @@ -8884,7 +8878,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp1 = EmitPointerWithAlignment(E->getArg(1)); - Ops.push_back(PtrOp1.emitRawPointer(*this)); + Ops.push_back(PtrOp1.getPointer()); continue; } } @@ -9305,7 +9299,7 @@ Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID, if (ReturnValue.isNull()) return MvecOut; else - return Builder.CreateStore(MvecOut, ReturnValue.getAddress()); + return Builder.CreateStore(MvecOut, ReturnValue.getValue()); } case CustomCodeGen::VST24: { @@ -11485,7 +11479,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.emitRawPointer(*this)); + Ops.push_back(PtrOp0.getPointer()); continue; } } @@ -13351,15 +13345,15 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID, if (!getDebugInfo()) { CGM.Error(E->getExprLoc(), "using __builtin_preserve_field_info() without -g"); - return IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) - : EmitLValue(Arg).emitRawPointer(*this); + return IsBitField ? EmitLValue(Arg).getBitFieldPointer() + : EmitLValue(Arg).getPointer(*this); } // Enable underlying preserve_*_access_index() generation. bool OldIsInPreservedAIRegion = IsInPreservedAIRegion; IsInPreservedAIRegion = true; - Value *FieldAddr = IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) - : EmitLValue(Arg).emitRawPointer(*this); + Value *FieldAddr = IsBitField ? EmitLValue(Arg).getBitFieldPointer() + : EmitLValue(Arg).getPointer(*this); IsInPreservedAIRegion = OldIsInPreservedAIRegion; ConstantInt *C = cast(EmitScalarExpr(E->getArg(1))); @@ -14351,14 +14345,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { - RawAddress Tmp = CreateMemTemp(E->getArg(0)->getType()); + Address Tmp = CreateMemTemp(E->getArg(0)->getType()); Builder.CreateStore(Ops[0], Tmp); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), Tmp.getPointer()); } case X86::BI_mm_getcsr: case X86::BI__builtin_ia32_stmxcsr: { - RawAddress Tmp = CreateMemTemp(E->getType()); + Address Tmp = CreateMemTemp(E->getType()); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), Tmp.getPointer()); return Builder.CreateLoad(Tmp, "stmxcsr"); @@ -17633,8 +17627,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, SmallVector Ops; for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) if (E->getArg(i)->getType()->isArrayType()) - Ops.push_back( - EmitArrayToPointerDecay(E->getArg(i)).emitRawPointer(*this)); + Ops.push_back(EmitArrayToPointerDecay(E->getArg(i)).getPointer()); else Ops.push_back(EmitScalarExpr(E->getArg(i))); // The first argument of these two builtins is a pointer used to store their @@ -20096,14 +20089,14 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, // Save returned values. assert(II.NumResults); if (II.NumResults == 1) { - Builder.CreateAlignedStore(Result, Dst.emitRawPointer(*this), + Builder.CreateAlignedStore(Result, Dst.getPointer(), CharUnits::fromQuantity(4)); } else { for (unsigned i = 0; i < II.NumResults; ++i) { Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), Dst.getElementType()), - Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), + Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); } @@ -20143,7 +20136,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < II.NumResults; ++i) { Value *V = Builder.CreateAlignedLoad( Src.getElementType(), - Builder.CreateGEP(Src.getElementType(), Src.emitRawPointer(*this), + Builder.CreateGEP(Src.getElementType(), Src.getPointer(), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, ParamType)); @@ -20215,7 +20208,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsA; ++i) { Value *V = Builder.CreateAlignedLoad( SrcA.getElementType(), - Builder.CreateGEP(SrcA.getElementType(), SrcA.emitRawPointer(*this), + Builder.CreateGEP(SrcA.getElementType(), SrcA.getPointer(), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, AType)); @@ -20225,7 +20218,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsB; ++i) { Value *V = Builder.CreateAlignedLoad( SrcB.getElementType(), - Builder.CreateGEP(SrcB.getElementType(), SrcB.emitRawPointer(*this), + Builder.CreateGEP(SrcB.getElementType(), SrcB.getPointer(), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, BType)); @@ -20236,7 +20229,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsC; ++i) { Value *V = Builder.CreateAlignedLoad( SrcC.getElementType(), - Builder.CreateGEP(SrcC.getElementType(), SrcC.emitRawPointer(*this), + Builder.CreateGEP(SrcC.getElementType(), SrcC.getPointer(), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, CType)); @@ -20246,7 +20239,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsD; ++i) Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), - Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), + Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); return Result; @@ -20504,7 +20497,7 @@ struct BuiltinAlignArgs { BuiltinAlignArgs(const CallExpr *E, CodeGenFunction &CGF) { QualType AstType = E->getArg(0)->getType(); if (AstType->isArrayType()) - Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(CGF); + Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).getPointer(); else Src = CGF.EmitScalarExpr(E->getArg(0)); SrcType = Src->getType(); @@ -21122,7 +21115,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_get: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); Value *Index = EmitScalarExpr(E->getArg(1)); Function *Callee; if (E->getType().isWebAssemblyExternrefType()) @@ -21136,7 +21129,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_set: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Function *Callee; @@ -21151,13 +21144,13 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_size: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Value = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *Value = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_table_size); return Builder.CreateCall(Callee, Value); } case WebAssembly::BI__builtin_wasm_table_grow: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); Value *Val = EmitScalarExpr(E->getArg(1)); Value *NElems = EmitScalarExpr(E->getArg(2)); @@ -21174,7 +21167,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_fill: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Value *NElems = EmitScalarExpr(E->getArg(3)); @@ -21192,8 +21185,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_copy: { assert(E->getArg(0)->getType()->isArrayType()); - Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); - Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).emitRawPointer(*this); + Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).getPointer(); Value *DstIdx = EmitScalarExpr(E->getArg(2)); Value *SrcIdx = EmitScalarExpr(E->getArg(3)); Value *NElems = EmitScalarExpr(E->getArg(4)); @@ -21272,7 +21265,7 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, auto MakeCircOp = [this, E](unsigned IntID, bool IsLoad) { // The base pointer is passed by address, so it needs to be loaded. Address A = EmitPointerWithAlignment(E->getArg(0)); - Address BP = Address(A.emitRawPointer(*this), Int8PtrTy, A.getAlignment()); + Address BP = Address(A.getPointer(), Int8PtrTy, A.getAlignment()); llvm::Value *Base = Builder.CreateLoad(BP); // The treatment of both loads and stores is the same: the arguments for // the builtin are the same as the arguments for the intrinsic. @@ -21313,8 +21306,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression // per call. Address DestAddr = EmitPointerWithAlignment(E->getArg(1)); - DestAddr = DestAddr.withElementType(Int8Ty); - llvm::Value *DestAddress = DestAddr.emitRawPointer(*this); + DestAddr = Address(DestAddr.getPointer(), Int8Ty, DestAddr.getAlignment()); + llvm::Value *DestAddress = DestAddr.getPointer(); // Operands are Base, Dest, Modifier. // The intrinsic format in LLVM IR is defined as @@ -21365,8 +21358,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), PredIn}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } // These are identical to the builtins above, except they don't consume @@ -21384,8 +21377,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 0cb5b06a519c..b756318c46a9 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -331,11 +331,11 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, llvm::ConstantInt::get(SizeTy, std::max(1, Args.size()))); // Store pointers to the arguments in a locally allocated launch_args. for (unsigned i = 0; i < Args.size(); ++i) { - llvm::Value *VarPtr = CGF.GetAddrOfLocalVar(Args[i]).emitRawPointer(CGF); + llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer(); llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, PtrTy); CGF.Builder.CreateDefaultAlignedStore( - VoidVarPtr, CGF.Builder.CreateConstGEP1_32( - PtrTy, KernelArgs.emitRawPointer(CGF), i)); + VoidVarPtr, + CGF.Builder.CreateConstGEP1_32(PtrTy, KernelArgs.getPointer(), i)); } llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); @@ -393,10 +393,9 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, /*isVarArg=*/false), addUnderscoredPrefixToName("PopCallConfiguration")); - CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, {GridDim.emitRawPointer(CGF), - BlockDim.emitRawPointer(CGF), - ShmemSize.emitRawPointer(CGF), - Stream.emitRawPointer(CGF)}); + CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, + {GridDim.getPointer(), BlockDim.getPointer(), + ShmemSize.getPointer(), Stream.getPointer()}); // Emit the call to cudaLaunch llvm::Value *Kernel = @@ -406,7 +405,7 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, cudaLaunchKernelFD->getParamDecl(0)->getType()); LaunchKernelArgs.add(RValue::getAggregate(GridDim), Dim3Ty); LaunchKernelArgs.add(RValue::getAggregate(BlockDim), Dim3Ty); - LaunchKernelArgs.add(RValue::get(KernelArgs, CGF), + LaunchKernelArgs.add(RValue::get(KernelArgs.getPointer()), cudaLaunchKernelFD->getParamDecl(3)->getType()); LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(ShmemSize)), cudaLaunchKernelFD->getParamDecl(4)->getType()); @@ -439,8 +438,8 @@ void CGNVCUDARuntime::emitDeviceStubBodyLegacy(CodeGenFunction &CGF, auto TInfo = CGM.getContext().getTypeInfoInChars(A->getType()); Offset = Offset.alignTo(TInfo.Align); llvm::Value *Args[] = { - CGF.Builder.CreatePointerCast( - CGF.GetAddrOfLocalVar(A).emitRawPointer(CGF), PtrTy), + CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(), + PtrTy), llvm::ConstantInt::get(SizeTy, TInfo.Width.getQuantity()), llvm::ConstantInt::get(SizeTy, Offset.getQuantity()), }; diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 7c6dfc3e59d8..a8bf57a277e9 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -20,12 +20,6 @@ using namespace CodeGen; CGCXXABI::~CGCXXABI() { } -Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) { - return CGF.makeNaturalAddressForPointer( - CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(), - CGF.CXXABIThisAlignment); -} - void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { DiagnosticsEngine &Diags = CGF.CGM.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -50,12 +44,8 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *MemPtr, const MemberPointerType *MPT) { ErrorUnsupportedABI(CGF, "calls through member pointers"); - const auto *RD = - cast(MPT->getClass()->castAs()->getDecl()); - ThisPtrForCall = - CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD)); - const FunctionProtoType *FPT = - MPT->getPointeeType()->getAs(); + ThisPtrForCall = This.getPointer(); + const auto *FPT = MPT->getPointeeType()->castAs(); llvm::Constant *FnPtr = llvm::Constant::getNullValue( llvm::PointerType::getUnqual(CGM.getLLVMContext())); return CGCallee::forDirect(FnPtr, FPT); @@ -261,15 +251,16 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, // If we don't need an array cookie, bail out early. if (!requiresArrayCookie(expr, eltTy)) { - allocPtr = ptr.emitRawPointer(CGF); + allocPtr = ptr.getPointer(); numElements = nullptr; cookieSize = CharUnits::Zero(); return; } cookieSize = getArrayCookieSizeImpl(eltTy); - Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); - allocPtr = allocAddr.emitRawPointer(CGF); + Address allocAddr = + CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); + allocPtr = allocAddr.getPointer(); numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); } diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index c7eccbd0095a..ad1ad08d0856 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -57,8 +57,12 @@ protected: llvm::Value *getThisValue(CodeGenFunction &CGF) { return CGF.CXXABIThisValue; } - - Address getThisAddress(CodeGenFunction &CGF); + Address getThisAddress(CodeGenFunction &CGF) { + return Address( + CGF.CXXABIThisValue, + CGF.ConvertTypeForMem(CGF.CXXABIThisDecl->getType()->getPointeeType()), + CGF.CXXABIThisAlignment); + } /// Issue a diagnostic about unsupported features in the ABI. void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S); @@ -471,6 +475,12 @@ public: BaseSubobject Base, const CXXRecordDecl *NearestVBase) = 0; + /// Get the address point of the vtable for the given base subobject while + /// building a constexpr. + virtual llvm::Constant * + getVTableAddressPointForConstExpr(BaseSubobject Base, + const CXXRecordDecl *VTableClass) = 0; + /// Get the address of the vtable for the given record decl which should be /// used for the vptr at the given offset in RD. virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index fb0078214b07..b8adf5c26b3a 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1037,9 +1037,15 @@ static void forConstantArrayExpansion(CodeGenFunction &CGF, ConstantArrayExpansion *CAE, Address BaseAddr, llvm::function_ref Fn) { + CharUnits EltSize = CGF.getContext().getTypeSizeInChars(CAE->EltTy); + CharUnits EltAlign = + BaseAddr.getAlignment().alignmentOfArrayElement(EltSize); + llvm::Type *EltTy = CGF.ConvertTypeForMem(CAE->EltTy); + for (int i = 0, n = CAE->NumElts; i < n; i++) { - Address EltAddr = CGF.Builder.CreateConstGEP2_32(BaseAddr, 0, i); - Fn(EltAddr); + llvm::Value *EltAddr = CGF.Builder.CreateConstGEP2_32( + BaseAddr.getElementType(), BaseAddr.getPointer(), 0, i); + Fn(Address(EltAddr, EltTy, EltAlign)); } } @@ -1154,10 +1160,9 @@ void CodeGenFunction::ExpandTypeToArgs( } /// Create a temporary allocation for the purposes of coercion. -static RawAddress CreateTempAllocaForCoercion(CodeGenFunction &CGF, - llvm::Type *Ty, - CharUnits MinAlign, - const Twine &Name = "tmp") { +static Address CreateTempAllocaForCoercion(CodeGenFunction &CGF, llvm::Type *Ty, + CharUnits MinAlign, + const Twine &Name = "tmp") { // Don't use an alignment that's worse than what LLVM would prefer. auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlign(Ty); CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign)); @@ -1327,11 +1332,11 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, } // Otherwise do coercion through memory. This is stupid, but simple. - RawAddress Tmp = + Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName()); CGF.Builder.CreateMemCpy( - Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), - Src.emitRawPointer(CGF), Src.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), Src.getPointer(), + Src.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinValue())); return CGF.Builder.CreateLoad(Tmp); } @@ -1415,12 +1420,11 @@ static void CreateCoercedStore(llvm::Value *Src, // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - RawAddress Tmp = - CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); + Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); CGF.Builder.CreateStore(Src, Tmp); CGF.Builder.CreateMemCpy( - Dst.emitRawPointer(CGF), Dst.getAlignment().getAsAlign(), - Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), + Dst.getPointer(), Dst.getAlignment().getAsAlign(), Tmp.getPointer(), + Tmp.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, DstSize.getFixedValue())); } } @@ -3020,17 +3024,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Indirect: case ABIArgInfo::IndirectAliased: { assert(NumIRArgs == 1); - Address ParamAddr = makeNaturalAddressForPointer( - Fn->getArg(FirstIRArg), Ty, ArgI.getIndirectAlign(), false, nullptr, - nullptr, KnownNonNull); + Address ParamAddr = Address(Fn->getArg(FirstIRArg), ConvertTypeForMem(Ty), + ArgI.getIndirectAlign(), KnownNonNull); if (!hasScalarEvaluationKind(Ty)) { // Aggregates and complex variables are accessed by reference. All we // need to do is realign the value, if requested. Also, if the address // may be aliased, copy it to ensure that the parameter variable is // mutable and has a unique adress, as C requires. + Address V = ParamAddr; if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) { - RawAddress AlignedTemp = CreateMemTemp(Ty, "coerce"); + Address AlignedTemp = CreateMemTemp(Ty, "coerce"); // Copy from the incoming argument pointer to the temporary with the // appropriate alignment. @@ -3040,12 +3044,11 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, CharUnits Size = getContext().getTypeSizeInChars(Ty); Builder.CreateMemCpy( AlignedTemp.getPointer(), AlignedTemp.getAlignment().getAsAlign(), - ParamAddr.emitRawPointer(*this), - ParamAddr.getAlignment().getAsAlign(), + ParamAddr.getPointer(), ParamAddr.getAlignment().getAsAlign(), llvm::ConstantInt::get(IntPtrTy, Size.getQuantity())); - ParamAddr = AlignedTemp; + V = AlignedTemp; } - ArgVals.push_back(ParamValue::forIndirect(ParamAddr)); + ArgVals.push_back(ParamValue::forIndirect(V)); } else { // Load scalar value from indirect argument. llvm::Value *V = @@ -3159,10 +3162,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, == ParameterABI::SwiftErrorResult) { QualType pointeeTy = Ty->getPointeeType(); assert(pointeeTy->isPointerType()); - RawAddress temp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - Address arg = makeNaturalAddressForPointer( - V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); + Address temp = + CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); + Address arg(V, ConvertTypeForMem(pointeeTy), + getContext().getTypeAlignInChars(pointeeTy)); llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); Builder.CreateStore(incomingErrorValue, temp); V = temp.getPointer(); @@ -3499,7 +3502,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, llvm::LoadInst *load = dyn_cast(retainedValue->stripPointerCasts()); if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) + load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer()) return nullptr; // Okay! Burn it all down. This relies for correctness on the @@ -3536,15 +3539,12 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { - llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); - // Check if a User is a store which pointerOperand is the ReturnValue. // We are looking for stores to the ReturnValue, not for stores of the // ReturnValue to some other location. - auto GetStoreIfValid = [&CGF, - ReturnValuePtr](llvm::User *U) -> llvm::StoreInst * { + auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * { auto *SI = dyn_cast(U); - if (!SI || SI->getPointerOperand() != ReturnValuePtr || + if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer() || SI->getValueOperand()->getType() != CGF.ReturnValue.getElementType()) return nullptr; // These aren't actually possible for non-coerced returns, and we @@ -3558,7 +3558,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { // for something immediately preceding the IP. Sometimes this can // happen with how we generate implicit-returns; it can also happen // with noreturn cleanups. - if (!ReturnValuePtr->hasOneUse()) { + if (!CGF.ReturnValue.getPointer()->hasOneUse()) { llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); if (IP->empty()) return nullptr; @@ -3576,7 +3576,8 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { return nullptr; } - llvm::StoreInst *store = GetStoreIfValid(ReturnValuePtr->user_back()); + llvm::StoreInst *store = + GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back()); if (!store) return nullptr; // Now do a first-and-dirty dominance check: just walk up the @@ -4120,11 +4121,7 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, } static bool isProvablyNull(llvm::Value *addr) { - return llvm::isa_and_nonnull(addr); -} - -static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { - return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); + return isa(addr); } /// Emit the actual writing-back of a writeback. @@ -4132,20 +4129,21 @@ static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; Address srcAddr = srcLV.getAddress(CGF); - assert(!isProvablyNull(srcAddr.getBasePointer()) && + assert(!isProvablyNull(srcAddr.getPointer()) && "shouldn't have writeback for provably null argument"); llvm::BasicBlock *contBB = nullptr; // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); - + bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), + CGF.CGM.getDataLayout()); if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); - llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); + llvm::Value *isNull = + CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); CGF.Builder.CreateCondBr(isNull, contBB, writebackBB); CGF.EmitBlock(writebackBB); } @@ -4249,7 +4247,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getBasePointer())) { + if (isProvablyNull(srcAddr.getPointer())) { args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), CRE->getType()); return; @@ -4278,16 +4276,17 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); - + bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), + CGF.CGM.getDataLayout()); if (provablyNonNull) { - finalArgument = temp.emitRawPointer(CGF); + finalArgument = temp.getPointer(); } else { - llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); + llvm::Value *isNull = + CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); - finalArgument = CGF.Builder.CreateSelect( - isNull, llvm::ConstantPointerNull::get(destType), - temp.emitRawPointer(CGF), "icr.argument"); + finalArgument = CGF.Builder.CreateSelect(isNull, + llvm::ConstantPointerNull::get(destType), + temp.getPointer(), "icr.argument"); // If we need to copy, then the load has to be conditional, which // means we need control flow. @@ -4411,16 +4410,6 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, std::nullopt); } -void CodeGenFunction::EmitNonNullArgCheck(Address Addr, QualType ArgType, - SourceLocation ArgLoc, - AbstractCallee AC, unsigned ParmNum) { - if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || - SanOpts.has(SanitizerKind::NullabilityArg))) - return; - - EmitNonNullArgCheck(RValue::get(Addr, *this), ArgType, ArgLoc, AC, ParmNum); -} - // Check if the call is going to use the inalloca convention. This needs to // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged // later, so we can't check it directly. @@ -4761,20 +4750,10 @@ CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) { llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const llvm::Twine &name) { - return EmitNounwindRuntimeCall(callee, ArrayRef(), name); + return EmitNounwindRuntimeCall(callee, std::nullopt, name); } /// Emits a call to the given nounwind runtime function. -llvm::CallInst * -CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, - ArrayRef
args, - const llvm::Twine &name) { - SmallVector values; - for (auto arg : args) - values.push_back(arg.emitRawPointer(*this)); - return EmitNounwindRuntimeCall(callee, values, name); -} - llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, @@ -5053,7 +5032,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If we're using inalloca, insert the allocation after the stack save. // FIXME: Do this earlier rather than hacking it in here! - RawAddress ArgMemory = RawAddress::invalid(); + Address ArgMemory = Address::invalid(); if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { const llvm::DataLayout &DL = CGM.getDataLayout(); llvm::Instruction *IP = CallArgs.getStackBase(); @@ -5069,7 +5048,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI->setAlignment(Align.getAsAlign()); AI->setUsedWithInAlloca(true); assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); - ArgMemory = RawAddress(AI, ArgStruct, Align); + ArgMemory = Address(AI, ArgStruct, Align); } ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo); @@ -5078,11 +5057,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); - RawAddress SRetAlloca = RawAddress::invalid(); + Address SRetAlloca = Address::invalid(); llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getAddress(); + SRetPtr = ReturnValue.getValue(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); if (HaveInsertPoint() && ReturnValue.isUnused()) { @@ -5092,16 +5071,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } if (IRFunctionArgs.hasSRetArg()) { - IRCallArgs[IRFunctionArgs.getSRetArgNo()] = - getAsNaturalPointerTo(SRetPtr, RetTy); + IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); } else if (RetAI.isInAlloca()) { Address Addr = Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex()); - Builder.CreateStore(getAsNaturalPointerTo(SRetPtr, RetTy), Addr); + Builder.CreateStore(SRetPtr.getPointer(), Addr); } } - RawAddress swiftErrorTemp = RawAddress::invalid(); + Address swiftErrorTemp = Address::invalid(); Address swiftErrorArg = Address::invalid(); // When passing arguments using temporary allocas, we need to add the @@ -5134,9 +5112,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 0); assert(getTarget().getTriple().getArch() == llvm::Triple::x86); if (I->isAggregate()) { - RawAddress Addr = I->hasLValue() - ? I->getKnownLValue().getAddress(*this) - : I->getKnownRValue().getAggregateAddress(); + Address Addr = I->hasLValue() + ? I->getKnownLValue().getAddress(*this) + : I->getKnownRValue().getAggregateAddress(); llvm::Instruction *Placeholder = cast(Addr.getPointer()); @@ -5160,7 +5138,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else if (ArgInfo.getInAllocaIndirect()) { // Make a temporary alloca and store the address of it into the argument // struct. - RawAddress Addr = CreateMemTempWithoutCast( + Address Addr = CreateMemTempWithoutCast( I->Ty, getContext().getTypeAlignInChars(I->Ty), "indirect-arg-temp"); I->copyInto(*this, Addr); @@ -5182,12 +5160,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 1); if (!I->isAggregate()) { // Make a temporary alloca to pass the argument. - RawAddress Addr = CreateMemTempWithoutCast( + Address Addr = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "indirect-arg-temp"); - llvm::Value *Val = getAsNaturalPointerTo(Addr, I->Ty); + llvm::Value *Val = Addr.getPointer(); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(Val); + Val = Builder.CreateFreeze(Addr.getPointer()); IRCallArgs[FirstIRArg] = Val; I->copyInto(*this, Addr); @@ -5203,6 +5181,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Address Addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); + llvm::Value *V = Addr.getPointer(); CharUnits Align = ArgInfo.getIndirectAlign(); const llvm::DataLayout *TD = &CGM.getDataLayout(); @@ -5213,9 +5192,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, bool NeedCopy = false; if (Addr.getAlignment() < Align && - llvm::getOrEnforceKnownAlignment(Addr.emitRawPointer(*this), - Align.getAsAlign(), - *TD) < Align.getAsAlign()) { + llvm::getOrEnforceKnownAlignment(V, Align.getAsAlign(), *TD) < + Align.getAsAlign()) { NeedCopy = true; } else if (I->hasLValue()) { auto LV = I->getKnownLValue(); @@ -5246,11 +5224,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (NeedCopy) { // Create an aligned temporary, and copy to it. - RawAddress AI = CreateMemTempWithoutCast( + Address AI = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); - llvm::Value *Val = getAsNaturalPointerTo(AI, I->Ty); + llvm::Value *Val = AI.getPointer(); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(Val); + Val = Builder.CreateFreeze(AI.getPointer()); IRCallArgs[FirstIRArg] = Val; // Emit lifetime markers for the temporary alloca. @@ -5267,7 +5245,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, I->copyInto(*this, AI); } else { // Skip the extra memcpy call. - llvm::Value *V = getAsNaturalPointerTo(Addr, I->Ty); auto *T = llvm::PointerType::get( CGM.getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace()); @@ -5307,8 +5284,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); QualType pointeeTy = I->Ty->getPointeeType(); - swiftErrorArg = makeNaturalAddressForPointer( - V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); + swiftErrorArg = Address(V, ConvertTypeForMem(pointeeTy), + getContext().getTypeAlignInChars(pointeeTy)); swiftErrorTemp = CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); @@ -5445,7 +5422,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *tempSize = nullptr; Address addr = Address::invalid(); - RawAddress AllocaAddr = RawAddress::invalid(); + Address AllocaAddr = Address::invalid(); if (I->isAggregate()) { addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); @@ -5879,7 +5856,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return RValue::getComplex(std::make_pair(Real, Imag)); } case TEK_Aggregate: { - Address DestPtr = ReturnValue.getAddress(); + Address DestPtr = ReturnValue.getValue(); bool DestIsVolatile = ReturnValue.isVolatile(); if (!DestPtr.isValid()) { diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 6b676ac196db..1bd48a072593 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -377,7 +377,6 @@ public: Address getValue() const { return Addr; } bool isUnused() const { return IsUnused; } bool isExternallyDestructed() const { return IsExternallyDestructed; } - Address getAddress() const { return Addr; } }; /// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 8c1c8ee455d2..34319381901a 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -139,9 +139,8 @@ Address CodeGenFunction::LoadCXXThisAddress() { CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent()); } - return makeNaturalAddressForPointer( - LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment, - false, nullptr, nullptr, KnownNonNull); + llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType()); + return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull); } /// Emit the address of a field using a member data pointer. @@ -271,7 +270,7 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, } // Apply the base offset. - llvm::Value *ptr = addr.emitRawPointer(CGF); + llvm::Value *ptr = addr.getPointer(); ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr"); // If we have a virtual component, the alignment of the result will @@ -339,8 +338,8 @@ Address CodeGenFunction::GetAddressOfBaseClass( if (sanitizePerformTypeCheck()) { SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, !NullCheckValue); - EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy, - DerivedAlign, SkippedChecks); + EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(), + DerivedTy, DerivedAlign, SkippedChecks); } return Value.withElementType(BaseValueTy); } @@ -355,7 +354,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull"); endBB = createBasicBlock("cast.end"); - llvm::Value *isNull = Builder.CreateIsNull(Value); + llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer()); Builder.CreateCondBr(isNull, endBB, notNullBB); EmitBlock(notNullBB); } @@ -364,15 +363,14 @@ Address CodeGenFunction::GetAddressOfBaseClass( SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, - Value.emitRawPointer(*this), DerivedTy, DerivedAlign, - SkippedChecks); + Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks); } // Compute the virtual offset. llvm::Value *VirtualOffset = nullptr; if (VBase) { VirtualOffset = - CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); + CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); } // Apply both offsets. @@ -389,7 +387,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( EmitBlock(endBB); llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result"); - PHI->addIncoming(Value.emitRawPointer(*this), notNullBB); + PHI->addIncoming(Value.getPointer(), notNullBB); PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB); Value = Value.withPointer(PHI, NotKnownNonNull); } @@ -426,19 +424,15 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, CastNotNull = createBasicBlock("cast.notnull"); CastEnd = createBasicBlock("cast.end"); - llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr); + llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer()); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } // Apply the offset. - Address Addr = BaseAddr.withElementType(Int8Ty); - Addr = Builder.CreateInBoundsGEP( - Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty, - CGM.getClassPointerAlignment(Derived), "sub.ptr"); - - // Just cast. - Addr = Addr.withElementType(DerivedValueTy); + llvm::Value *Value = BaseAddr.getPointer(); + Value = Builder.CreateInBoundsGEP( + Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr"); // Produce a PHI if we had a null-check. if (NullCheckValue) { @@ -447,15 +441,13 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, Builder.CreateBr(CastEnd); EmitBlock(CastEnd); - llvm::Value *Value = Addr.emitRawPointer(*this); llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); PHI->addIncoming(Value, CastNotNull); PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); - return Address(PHI, Addr.getElementType(), - CGM.getClassPointerAlignment(Derived)); + Value = PHI; } - return Addr; + return Address(Value, DerivedValueTy, CGM.getClassPointerAlignment(Derived)); } llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, @@ -1727,7 +1719,7 @@ namespace { // Use the base class declaration location as inline DebugLocation. All // fields of the class are destroyed. DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass); - EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF), + EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(), BaseSize.getQuantity()); // Prevent the current stack frame from disappearing from the stack trace. @@ -2030,7 +2022,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, // Find the end of the array. llvm::Type *elementType = arrayBase.getElementType(); - llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this); + llvm::Value *arrayBegin = arrayBase.getPointer(); llvm::Value *arrayEnd = Builder.CreateInBoundsGEP( elementType, arrayBegin, numElements, "arrayctor.end"); @@ -2126,15 +2118,14 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, Address This = ThisAVS.getAddress(); LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace(); - llvm::Value *ThisPtr = - getAsNaturalPointerTo(This, D->getThisType()->getPointeeType()); + llvm::Value *ThisPtr = This.getPointer(); if (SlotAS != ThisAS) { unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); llvm::Type *NewType = llvm::PointerType::get(getLLVMContext(), TargetThisAS); - ThisPtr = getTargetHooks().performAddrSpaceCast(*this, ThisPtr, ThisAS, - SlotAS, NewType); + ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), + ThisAS, SlotAS, NewType); } // Push the this ptr. @@ -2203,7 +2194,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const CXXRecordDecl *ClassDecl = D->getParent(); if (!NewPointerIsChecked) - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This, + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), getContext().getRecordType(ClassDecl), CharUnits::Zero()); if (D->isTrivial() && D->isDefaultConstructor()) { @@ -2216,9 +2207,10 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // model that copy. if (isMemcpyEquivalentSpecialMember(D)) { assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); + QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); - Address Src = makeNaturalAddressForPointer( - Args[1].getRValue(*this).getScalarVal(), SrcTy); + Address Src = Address(Args[1].getRValue(*this).getScalarVal(), ConvertTypeForMem(SrcTy), + CGM.getNaturalTypeAlignment(SrcTy)); LValue SrcLVal = MakeAddrLValue(Src, SrcTy); QualType DestTy = getContext().getTypeDeclType(ClassDecl); LValue DestLVal = MakeAddrLValue(This, DestTy); @@ -2271,9 +2263,7 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall( const CXXConstructorDecl *D, bool ForVirtualBase, Address This, bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) { CallArgList Args; - CallArg ThisArg(RValue::get(getAsNaturalPointerTo( - This, D->getThisType()->getPointeeType())), - D->getThisType()); + CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType()); // Forward the parameters. if (InheritedFromVBase && @@ -2398,14 +2388,12 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, CallArgList Args; // Push the this ptr. - Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())), - D->getThisType()); + Args.add(RValue::get(This.getPointer()), D->getThisType()); // Push the src ptr. QualType QT = *(FPT->param_type_begin()); llvm::Type *t = CGM.getTypes().ConvertType(QT); - llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType()); - llvm::Value *SrcVal = Builder.CreateBitCast(Val, t); + llvm::Value *SrcVal = Builder.CreateBitCast(Src.getPointer(), t); Args.add(RValue::get(SrcVal), QT); // Skip over first argument (Src). @@ -2430,9 +2418,7 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // this Address This = LoadCXXThisAddress(); - DelegateArgs.add(RValue::get(getAsNaturalPointerTo( - This, (*I)->getType()->getPointeeType())), - (*I)->getType()); + DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); ++I; // FIXME: The location of the VTT parameter in the parameter list is @@ -2789,7 +2775,7 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived, if (MayBeNull) { llvm::Value *DerivedNotNull = - Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull"); + Builder.CreateIsNotNull(Derived.getPointer(), "cast.nonnull"); llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check"); ContBlock = createBasicBlock("cast.cont"); @@ -2990,7 +2976,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); Address ThisPtr = GetAddrOfBlockDecl(variable); - CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType); + CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); // Add the rest of the parameters. for (auto *param : BD->parameters()) @@ -3018,7 +3004,7 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { QualType LambdaType = getContext().getRecordType(Lambda); QualType ThisType = getContext().getPointerType(LambdaType); Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); - CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType); + CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); EmitLambdaDelegatingInvokeBody(MD, CallArgs); } diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index e6f8e6873004..f87caf050eea 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -27,7 +27,7 @@ bool DominatingValue::saved_type::needsSaving(RValue rv) { if (rv.isScalar()) return DominatingLLVMValue::needsSaving(rv.getScalarVal()); if (rv.isAggregate()) - return DominatingValue
::needsSaving(rv.getAggregateAddress()); + return DominatingLLVMValue::needsSaving(rv.getAggregatePointer()); return true; } @@ -35,40 +35,69 @@ DominatingValue::saved_type DominatingValue::saved_type::save(CodeGenFunction &CGF, RValue rv) { if (rv.isScalar()) { llvm::Value *V = rv.getScalarVal(); - return saved_type(DominatingLLVMValue::save(CGF, V), - DominatingLLVMValue::needsSaving(V) ? ScalarAddress - : ScalarLiteral); + + // These automatically dominate and don't need to be saved. + if (!DominatingLLVMValue::needsSaving(V)) + return saved_type(V, nullptr, ScalarLiteral); + + // Everything else needs an alloca. + Address addr = + CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue"); + CGF.Builder.CreateStore(V, addr); + return saved_type(addr.getPointer(), nullptr, ScalarAddress); } if (rv.isComplex()) { CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); - return saved_type(DominatingLLVMValue::save(CGF, V.first), - DominatingLLVMValue::save(CGF, V.second)); + llvm::Type *ComplexTy = + llvm::StructType::get(V.first->getType(), V.second->getType()); + Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex"); + CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0)); + CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1)); + return saved_type(addr.getPointer(), nullptr, ComplexAddress); } assert(rv.isAggregate()); - Address V = rv.getAggregateAddress(); - return saved_type( - DominatingValue
::save(CGF, V), rv.isVolatileQualified(), - DominatingValue
::needsSaving(V) ? AggregateAddress - : AggregateLiteral); + Address V = rv.getAggregateAddress(); // TODO: volatile? + if (!DominatingLLVMValue::needsSaving(V.getPointer())) + return saved_type(V.getPointer(), V.getElementType(), AggregateLiteral, + V.getAlignment().getQuantity()); + + Address addr = + CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue"); + CGF.Builder.CreateStore(V.getPointer(), addr); + return saved_type(addr.getPointer(), V.getElementType(), AggregateAddress, + V.getAlignment().getQuantity()); } /// Given a saved r-value produced by SaveRValue, perform the code /// necessary to restore it to usability at the current insertion /// point. RValue DominatingValue::saved_type::restore(CodeGenFunction &CGF) { + auto getSavingAddress = [&](llvm::Value *value) { + auto *AI = cast(value); + return Address(value, AI->getAllocatedType(), + CharUnits::fromQuantity(AI->getAlign().value())); + }; switch (K) { case ScalarLiteral: + return RValue::get(Value); case ScalarAddress: - return RValue::get(DominatingLLVMValue::restore(CGF, Vals.first)); + return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value))); case AggregateLiteral: - case AggregateAddress: return RValue::getAggregate( - DominatingValue
::restore(CGF, AggregateAddr), IsVolatile); + Address(Value, ElementType, CharUnits::fromQuantity(Align))); + case AggregateAddress: { + auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value)); + return RValue::getAggregate( + Address(addr, ElementType, CharUnits::fromQuantity(Align))); + } case ComplexAddress: { - llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first); - llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second); + Address address = getSavingAddress(Value); + llvm::Value *real = + CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 0)); + llvm::Value *imag = + CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 1)); return RValue::getComplex(real, imag); } } @@ -265,14 +294,14 @@ void EHScopeStack::popNullFixups() { BranchFixups.pop_back(); } -RawAddress CodeGenFunction::createCleanupActiveFlag() { +Address CodeGenFunction::createCleanupActiveFlag() { // Create a variable to decide whether the cleanup needs to be run. - RawAddress active = CreateTempAllocaWithoutCast( + Address active = CreateTempAllocaWithoutCast( Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); // Initialize it to false at a site that's guaranteed to be run // before each evaluation. - setBeforeOutermostConditional(Builder.getFalse(), active, *this); + setBeforeOutermostConditional(Builder.getFalse(), active); // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); @@ -280,7 +309,7 @@ RawAddress CodeGenFunction::createCleanupActiveFlag() { return active; } -void CodeGenFunction::initFullExprCleanupWithFlag(RawAddress ActiveFlag) { +void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { // Set that as the active flag in the cleanup. EHCleanupScope &cleanup = cast(*EHStack.begin()); assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); @@ -293,17 +322,15 @@ void CodeGenFunction::initFullExprCleanupWithFlag(RawAddress ActiveFlag) { void EHScopeStack::Cleanup::anchor() {} static void createStoreInstBefore(llvm::Value *value, Address addr, - llvm::Instruction *beforeInst, - CodeGenFunction &CGF) { - auto store = new llvm::StoreInst(value, addr.emitRawPointer(CGF), beforeInst); + llvm::Instruction *beforeInst) { + auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); store->setAlignment(addr.getAlignment().getAsAlign()); } static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, - llvm::Instruction *beforeInst, - CodeGenFunction &CGF) { - return new llvm::LoadInst(addr.getElementType(), addr.emitRawPointer(CGF), - name, false, addr.getAlignment().getAsAlign(), + llvm::Instruction *beforeInst) { + return new llvm::LoadInst(addr.getElementType(), addr.getPointer(), name, + false, addr.getAlignment().getAsAlign(), beforeInst); } @@ -330,8 +357,8 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF, // entry which we're currently popping. if (Fixup.OptimisticBranchBlock == nullptr) { createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex), - CGF.getNormalCleanupDestSlot(), Fixup.InitialBranch, - CGF); + CGF.getNormalCleanupDestSlot(), + Fixup.InitialBranch); Fixup.InitialBranch->setSuccessor(0, CleanupEntry); } @@ -358,7 +385,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, if (llvm::BranchInst *Br = dyn_cast(Term)) { assert(Br->isUnconditional()); auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(), - "cleanup.dest", Term, CGF); + "cleanup.dest", Term); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); Br->eraseFromParent(); @@ -486,8 +513,8 @@ void CodeGenFunction::PopCleanupBlocks( I += Header.getSize(); if (Header.isConditional()) { - RawAddress ActiveFlag = - reinterpret_cast(LifetimeExtendedCleanupStack[I]); + Address ActiveFlag = + reinterpret_cast
(LifetimeExtendedCleanupStack[I]); initFullExprCleanupWithFlag(ActiveFlag); I += sizeof(ActiveFlag); } @@ -861,7 +888,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (NormalCleanupDestSlot->hasOneUse()) { NormalCleanupDestSlot->user_back()->eraseFromParent(); NormalCleanupDestSlot->eraseFromParent(); - NormalCleanupDest = RawAddress::invalid(); + NormalCleanupDest = Address::invalid(); } llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); @@ -885,8 +912,9 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // pass the abnormal exit flag to Fn (SEH cleanup) cleanupFlags.setHasExitSwitch(); - llvm::LoadInst *Load = createLoadInstBefore( - getNormalCleanupDestSlot(), "cleanup.dest", nullptr, *this); + llvm::LoadInst *Load = + createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest", + nullptr); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Default, SwitchCapacity); @@ -933,8 +961,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (!Fixup.Destination) continue; if (!Fixup.OptimisticBranchBlock) { createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex), - getNormalCleanupDestSlot(), Fixup.InitialBranch, - *this); + getNormalCleanupDestSlot(), + Fixup.InitialBranch); Fixup.InitialBranch->setSuccessor(0, NormalEntry); } Fixup.OptimisticBranchBlock = NormalExit; @@ -1107,7 +1135,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { // Store the index at the start. llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); - createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI, *this); + createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI); // Adjust BI to point to the first cleanup block. { @@ -1241,9 +1269,9 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF, // If we're in a conditional block, ignore the dominating IP and // use the outermost conditional branch. if (CGF.isInConditionalBranch()) { - CGF.setBeforeOutermostConditional(value, var, CGF); + CGF.setBeforeOutermostConditional(value, var); } else { - createStoreInstBefore(value, var, dominatingIP, CGF); + createStoreInstBefore(value, var, dominatingIP); } } @@ -1293,7 +1321,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, Scope.setActive(false); } -RawAddress CodeGenFunction::getNormalCleanupDestSlot() { +Address CodeGenFunction::getNormalCleanupDestSlot() { if (!NormalCleanupDest.isValid()) NormalCleanupDest = CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h index 03e4a29d7b3d..7a7344c07160 100644 --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -333,7 +333,7 @@ public: Address getActiveFlag() const { return ActiveFlag; } - void setActiveFlag(RawAddress Var) { + void setActiveFlag(Address Var) { assert(Var.getAlignment().isOne()); ActiveFlag = Var; } diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 93ca711f716f..b7142ec08af9 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -867,8 +867,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { EmitStmt(S.getPromiseDeclStmt()); Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl()); - auto *PromiseAddrVoidPtr = new llvm::BitCastInst( - PromiseAddr.emitRawPointer(*this), VoidPtrTy, "", CoroId); + auto *PromiseAddrVoidPtr = + new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId); // Update CoroId to refer to the promise. We could not do it earlier because // promise local variable was not emitted yet. CoroId->setArgOperand(1, PromiseAddrVoidPtr); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 267f2e40a7bb..2ef5ed04af30 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1461,7 +1461,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { bool EmitDebugInfo = DI && CGM.getCodeGenOpts().hasReducedDebugInfo(); Address address = Address::invalid(); - RawAddress AllocaAddr = RawAddress::invalid(); + Address AllocaAddr = Address::invalid(); Address OpenMPLocalAddr = Address::invalid(); if (CGM.getLangOpts().OpenMPIRBuilder) OpenMPLocalAddr = OMPBuilderCBHelpers::getAddressOfLocalVariable(*this, &D); @@ -1524,10 +1524,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // return slot, so that we can elide the copy when returning this // variable (C++0x [class.copy]p34). address = ReturnValue; - AllocaAddr = - RawAddress(ReturnValue.emitRawPointer(*this), - ReturnValue.getElementType(), ReturnValue.getAlignment()); - ; + AllocaAddr = ReturnValue; if (const RecordType *RecordTy = Ty->getAs()) { const auto *RD = RecordTy->getDecl(); @@ -1538,7 +1535,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // to this variable. Set it to zero to indicate that NRVO was not // applied. llvm::Value *Zero = Builder.getFalse(); - RawAddress NRVOFlag = + Address NRVOFlag = CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo"); EnsureInsertPoint(); Builder.CreateStore(Zero, NRVOFlag); @@ -1681,7 +1678,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { } if (D.hasAttr() && HaveInsertPoint()) - EmitVarAnnotations(&D, address.emitRawPointer(*this)); + EmitVarAnnotations(&D, address.getPointer()); // Make sure we call @llvm.lifetime.end. if (emission.useLifetimeMarkers()) @@ -1854,13 +1851,12 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, llvm::Value *BaseSizeInChars = llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); Address Begin = Loc.withElementType(Int8Ty); - llvm::Value *End = Builder.CreateInBoundsGEP(Begin.getElementType(), - Begin.emitRawPointer(*this), - SizeVal, "vla.end"); + llvm::Value *End = Builder.CreateInBoundsGEP( + Begin.getElementType(), Begin.getPointer(), SizeVal, "vla.end"); llvm::BasicBlock *OriginBB = Builder.GetInsertBlock(); EmitBlock(LoopBB); llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur"); - Cur->addIncoming(Begin.emitRawPointer(*this), OriginBB); + Cur->addIncoming(Begin.getPointer(), OriginBB); CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); auto *I = Builder.CreateMemCpy(Address(Cur, Int8Ty, CurAlign), @@ -2287,7 +2283,7 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, checkZeroLength = false; } - llvm::Value *begin = addr.emitRawPointer(*this); + llvm::Value *begin = addr.getPointer(); llvm::Value *end = Builder.CreateInBoundsGEP(addr.getElementType(), begin, length); emitArrayDestroy(begin, end, type, elementAlign, destroyer, @@ -2547,7 +2543,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } Address DeclPtr = Address::invalid(); - RawAddress AllocaPtr = Address::invalid(); + Address AllocaPtr = Address::invalid(); bool DoStore = false; bool IsScalar = hasScalarEvaluationKind(Ty); bool UseIndirectDebugAddress = false; @@ -2559,8 +2555,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // Indirect argument is in alloca address space, which may be different // from the default address space. auto AllocaAS = CGM.getASTAllocaAddressSpace(); - auto *V = DeclPtr.emitRawPointer(*this); - AllocaPtr = RawAddress(V, DeclPtr.getElementType(), DeclPtr.getAlignment()); + auto *V = DeclPtr.getPointer(); + AllocaPtr = DeclPtr; // For truly ABI indirect arguments -- those that are not `byval` -- store // the address of the argument on the stack to preserve debug information. @@ -2699,7 +2695,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } if (D.hasAttr()) - EmitVarAnnotations(&D, DeclPtr.emitRawPointer(*this)); + EmitVarAnnotations(&D, DeclPtr.getPointer()); // We can only check return value nullability if all arguments to the // function satisfy their nullability preconditions. This makes it necessary diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 34f289334a7d..5a9d06da12de 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -397,7 +397,7 @@ namespace { void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { // Make sure the exception object is cleaned up if there's an // exception during initialization. - pushFullExprCleanup(EHCleanup, addr.emitRawPointer(*this)); + pushFullExprCleanup(EHCleanup, addr.getPointer()); EHScopeStack::stable_iterator cleanup = EHStack.stable_begin(); // __cxa_allocate_exception returns a void*; we need to cast this @@ -416,8 +416,8 @@ void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { /*IsInit*/ true); // Deactivate the cleanup block. - DeactivateCleanupBlock( - cleanup, cast(typedAddr.emitRawPointer(*this))); + DeactivateCleanupBlock(cleanup, + cast(typedAddr.getPointer())); } Address CodeGenFunction::getExceptionSlot() { @@ -1834,8 +1834,7 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, llvm::Value *ParentFP) { llvm::CallInst *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = - dyn_cast_or_null(ParentVar.getBasePointer())) { + if (auto *ParentAlloca = dyn_cast(ParentVar.getPointer())) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( @@ -1852,8 +1851,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, // If the parent didn't have an alloca, we're doing some nested outlining. // Just clone the existing localrecover call, but tweak the FP argument to // use our FP value. All other arguments are constants. - auto *ParentRecover = cast( - ParentVar.emitRawPointer(*this)->stripPointerCasts()); + auto *ParentRecover = + cast(ParentVar.getPointer()->stripPointerCasts()); assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && "expected alloca or localrecover in parent LocalDeclMap"); RecoverCall = cast(ParentRecover->clone()); @@ -1926,8 +1925,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, if (isa(D) && D->getType() == getContext().VoidPtrTy) { assert(D->getName().starts_with("frame_pointer")); - FramePtrAddrAlloca = - cast(I.second.getBasePointer()); + FramePtrAddrAlloca = cast(I.second.getPointer()); break; } } @@ -1988,8 +1986,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - CXXThisValue = - ThisFieldLValue.getAddress(*this).emitRawPointer(*this); + CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); } else { CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) .getScalarVal(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 36872c0fedb7..6491835cf8ef 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -65,21 +65,21 @@ static llvm::cl::opt ClSanitizeDebugDeoptimization( /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. -RawAddress -CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize) { +Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, + CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize) { auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); Alloca->setAlignment(Align.getAsAlign()); - return RawAddress(Alloca, Ty, Align, KnownNonNull); + return Address(Alloca, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. The alloca is casted to default address space if necessary. -RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize, - RawAddress *AllocaAddr) { +Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize, + Address *AllocaAddr) { auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); if (AllocaAddr) *AllocaAddr = Alloca; @@ -101,7 +101,7 @@ RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, Ty->getPointerTo(DestAddrSpace), /*non-null*/ true); } - return RawAddress(V, Ty, Align, KnownNonNull); + return Address(V, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates an alloca and inserts it into the entry @@ -120,29 +120,28 @@ llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, /// default alignment of the corresponding LLVM type, which is *not* /// guaranteed to be related in any way to the expected alignment of /// an AST type that might have been lowered to Ty. -RawAddress CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name) { +Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name) { CharUnits Align = CharUnits::fromQuantity(CGM.getDataLayout().getPrefTypeAlign(Ty)); return CreateTempAlloca(Ty, Align, Name); } -RawAddress CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { +Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { CharUnits Align = getContext().getTypeAlignInChars(Ty); return CreateTempAlloca(ConvertType(Ty), Align, Name); } -RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, - RawAddress *Alloca) { +Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, + Address *Alloca) { // FIXME: Should we prefer the preferred type alignment here? return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca); } -RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, - const Twine &Name, - RawAddress *Alloca) { - RawAddress Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, - /*ArraySize=*/nullptr, Alloca); +Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, + const Twine &Name, Address *Alloca) { + Address Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, + /*ArraySize=*/nullptr, Alloca); if (Ty->isConstantMatrixType()) { auto *ArrayTy = cast(Result.getElementType()); @@ -155,14 +154,13 @@ RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, return Result; } -RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, - CharUnits Align, - const Twine &Name) { +Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align, + const Twine &Name) { return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name); } -RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, - const Twine &Name) { +Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + const Twine &Name) { return CreateMemTempWithoutCast(Ty, getContext().getTypeAlignInChars(Ty), Name); } @@ -361,7 +359,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } else { CleanupFn = CGF.CGM.getAddrAndTypeOfCXXStructor( GlobalDecl(ReferenceTemporaryDtor, Dtor_Complete)); - CleanupArg = cast(ReferenceTemporary.emitRawPointer(CGF)); + CleanupArg = cast(ReferenceTemporary.getPointer()); } CGF.CGM.getCXXABI().registerGlobalDtor( CGF, *cast(M->getExtendingDecl()), CleanupFn, CleanupArg); @@ -386,10 +384,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } } -static RawAddress createReferenceTemporary(CodeGenFunction &CGF, - const MaterializeTemporaryExpr *M, - const Expr *Inner, - RawAddress *Alloca = nullptr) { +static Address createReferenceTemporary(CodeGenFunction &CGF, + const MaterializeTemporaryExpr *M, + const Expr *Inner, + Address *Alloca = nullptr) { auto &TCG = CGF.getTargetHooks(); switch (M->getStorageDuration()) { case SD_FullExpression: @@ -418,7 +416,7 @@ static RawAddress createReferenceTemporary(CodeGenFunction &CGF, GV->getValueType()->getPointerTo( CGF.getContext().getTargetAddressSpace(LangAS::Default))); // FIXME: Should we put the new global into a COMDAT? - return RawAddress(C, GV->getValueType(), alignment); + return Address(C, GV->getValueType(), alignment); } return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca); } @@ -450,7 +448,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { auto ownership = M->getType().getObjCLifetime(); if (ownership != Qualifiers::OCL_None && ownership != Qualifiers::OCL_ExplicitNone) { - RawAddress Object = createReferenceTemporary(*this, M, E); + Address Object = createReferenceTemporary(*this, M, E); if (auto *Var = dyn_cast(Object.getPointer())) { llvm::Type *Ty = ConvertTypeForMem(E->getType()); Object = Object.withElementType(Ty); @@ -504,8 +502,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { } // Create and initialize the reference temporary. - RawAddress Alloca = Address::invalid(); - RawAddress Object = createReferenceTemporary(*this, M, E, &Alloca); + Address Alloca = Address::invalid(); + Address Object = createReferenceTemporary(*this, M, E, &Alloca); if (auto *Var = dyn_cast( Object.getPointer()->stripPointerCasts())) { llvm::Type *TemporaryType = ConvertTypeForMem(E->getType()); @@ -1113,12 +1111,12 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( } else if (const MemberExpr *ME = dyn_cast(StructBase)) { LValue LV = EmitMemberExpr(ME); Address Addr = LV.getAddress(*this); - Res = Addr.emitRawPointer(*this); + Res = Addr.getPointer(); } else if (StructBase->getType()->isPointerType()) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo); - Res = Addr.emitRawPointer(*this); + Res = Addr.getPointer(); } else { return nullptr; } @@ -1284,7 +1282,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { if (BaseInfo) BaseInfo->mergeForCast(TargetTypeBaseInfo); - Addr.setAlignment(Align); + Addr = Address(Addr.getPointer(), Addr.getElementType(), Align, + IsKnownNonNull); } } @@ -1301,8 +1300,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, CGF.ConvertTypeForMem(E->getType()->getPointeeType()); Addr = Addr.withElementType(ElemTy); if (CE->getCastKind() == CK_AddressSpaceConversion) - Addr = CGF.Builder.CreateAddrSpaceCast( - Addr, CGF.ConvertType(E->getType()), ElemTy); + Addr = CGF.Builder.CreateAddrSpaceCast(Addr, + CGF.ConvertType(E->getType())); return Addr; } break; @@ -1365,9 +1364,10 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. - return CGF.makeNaturalAddressForPointer( - CGF.EmitScalarExpr(E), E->getType()->getPointeeType(), CharUnits(), - /*ForPointeeType=*/true, BaseInfo, TBAAInfo, IsKnownNonNull); + CharUnits Align = + CGF.CGM.getNaturalPointeeTypeAlignment(E->getType(), BaseInfo, TBAAInfo); + llvm::Type *ElemTy = CGF.ConvertTypeForMem(E->getType()->getPointeeType()); + return Address(CGF.EmitScalarExpr(E), ElemTy, Align, IsKnownNonNull); } /// EmitPointerWithAlignment - Given an expression of pointer type, try to @@ -1468,7 +1468,8 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) { if (IsBaseCXXThis || isa(ME->getBase())) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(TCK, E->getExprLoc(), LV, E->getType(), SkippedChecks); + EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(*this), E->getType(), + LV.getAlignment(), SkippedChecks); } return LV; } @@ -1580,11 +1581,11 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, // Defend against branches out of gnu statement expressions surrounded by // cleanups. Address Addr = LV.getAddress(*this); - llvm::Value *V = Addr.getBasePointer(); + llvm::Value *V = Addr.getPointer(); Scope.ForceCleanup({&V}); - Addr.replaceBasePointer(V); - return LValue::MakeAddr(Addr, LV.getType(), getContext(), - LV.getBaseInfo(), LV.getTBAAInfo()); + return LValue::MakeAddr(Addr.withPointer(V, Addr.isKnownNonNull()), + LV.getType(), getContext(), LV.getBaseInfo(), + LV.getTBAAInfo()); } // FIXME: Is it possible to create an ExprWithCleanups that produces a // bitfield lvalue or some other non-simple lvalue? @@ -1928,7 +1929,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getBasePointer())) + if (auto *GV = dyn_cast(Addr.getPointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2038,9 +2039,8 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) { // Convert the pointer of \p Addr to a pointer to a vector (the value type of // MatrixType), if it points to a array (the memory type of MatrixType). -static RawAddress MaybeConvertMatrixAddress(RawAddress Addr, - CodeGenFunction &CGF, - bool IsVector = true) { +static Address MaybeConvertMatrixAddress(Address Addr, CodeGenFunction &CGF, + bool IsVector = true) { auto *ArrayTy = dyn_cast(Addr.getElementType()); if (ArrayTy && IsVector) { auto *VectorTy = llvm::FixedVectorType::get(ArrayTy->getElementType(), @@ -2077,7 +2077,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isInit, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getBasePointer())) + if (auto *GV = dyn_cast(Addr.getPointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2432,12 +2432,14 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); llvm::Type *ResultType = IntPtrTy; Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); - llvm::Value *RHS = dst.emitRawPointer(*this); + llvm::Value *RHS = dst.getPointer(); RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - llvm::Value *LHS = Builder.CreatePtrToInt(LvalueDst.emitRawPointer(*this), - ResultType, "sub.ptr.lhs.cast"); + llvm::Value *LHS = + Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, + "sub.ptr.lhs.cast"); llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, BytesBetween); + CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, + BytesBetween); } else if (Dst.isGlobalObjCRef()) { CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, Dst.isThreadLocalRef()); @@ -2768,9 +2770,12 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(*this), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), - CharUnits(), /*ForPointeeType=*/true, - PointeeBaseInfo, PointeeTBAAInfo); + + QualType PointeeType = RefLVal.getType()->getPointeeType(); + CharUnits Align = CGM.getNaturalTypeAlignment( + PointeeType, PointeeBaseInfo, PointeeTBAAInfo, + /* forPointeeType= */ true); + return Address(Load, ConvertTypeForMem(PointeeType), Align); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { @@ -2787,9 +2792,10 @@ Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, LValueBaseInfo *BaseInfo, TBAAAccessInfo *TBAAInfo) { llvm::Value *Addr = Builder.CreateLoad(Ptr); - return makeNaturalAddressForPointer(Addr, PtrTy->getPointeeType(), - CharUnits(), /*ForPointeeType=*/true, - BaseInfo, TBAAInfo); + return Address(Addr, ConvertTypeForMem(PtrTy->getPointeeType()), + CGM.getNaturalTypeAlignment(PtrTy->getPointeeType(), BaseInfo, + TBAAInfo, + /*forPointeeType=*/true)); } LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, @@ -2985,7 +2991,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { /* BaseInfo= */ nullptr, /* TBAAInfo= */ nullptr, /* forPointeeType= */ true); - Addr = makeNaturalAddressForPointer(Val, T, Alignment); + Addr = Address(Val, ConvertTypeForMem(E->getType()), Alignment); } return MakeAddrLValue(Addr, T, AlignmentSource::Decl); } @@ -3017,12 +3023,11 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), CapturedStmtInfo->getContextValue()); Address LValueAddress = CapLVal.getAddress(*this); - CapLVal = MakeAddrLValue(Address(LValueAddress.emitRawPointer(*this), - LValueAddress.getElementType(), - getContext().getDeclAlign(VD)), - CapLVal.getType(), - LValueBaseInfo(AlignmentSource::Decl), - CapLVal.getTBAAInfo()); + CapLVal = MakeAddrLValue( + Address(LValueAddress.getPointer(), LValueAddress.getElementType(), + getContext().getDeclAlign(VD)), + CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl), + CapLVal.getTBAAInfo()); // Mark lvalue as nontemporal if the variable is marked as nontemporal // in simd context. if (getLangOpts().OpenMP && @@ -3078,8 +3083,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // Handle threadlocal function locals. if (VD->getTLSKind() != VarDecl::TLS_None) addr = addr.withPointer( - Builder.CreateThreadLocalAddress(addr.getBasePointer()), - NotKnownNonNull); + Builder.CreateThreadLocalAddress(addr.getPointer()), NotKnownNonNull); // Check for OpenMP threadprivate variables. if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && @@ -3347,7 +3351,7 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) { // Pointers are passed directly, everything else is passed by address. if (!V->getType()->isPointerTy()) { - RawAddress Ptr = CreateDefaultAlignTempAlloca(V->getType()); + Address Ptr = CreateDefaultAlignTempAlloca(V->getType()); Builder.CreateStore(V, Ptr); V = Ptr.getPointer(); } @@ -3920,21 +3924,6 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, } } -static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, - ArrayRef indices, - llvm::Type *elementType, bool inbounds, - bool signedIndices, SourceLocation loc, - CharUnits align, - const llvm::Twine &name = "arrayidx") { - if (inbounds) { - return CGF.EmitCheckedInBoundsGEP(addr, indices, elementType, signedIndices, - CodeGenFunction::NotSubtraction, loc, - align, name); - } else { - return CGF.Builder.CreateGEP(addr, indices, elementType, align, name); - } -} - static CharUnits getArrayElementAlign(CharUnits arrayAlign, llvm::Value *idx, CharUnits eltSize) { @@ -3982,7 +3971,7 @@ static Address wrapWithBPFPreserveStaticOffset(CodeGenFunction &CGF, llvm::Function *Fn = CGF.CGM.getIntrinsic(llvm::Intrinsic::preserve_static_offset); - llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.emitRawPointer(CGF)}); + llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.getPointer()}); return Address(Call, Addr.getElementType(), Addr.getAlignment()); } @@ -4045,7 +4034,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, // We can use that to compute the best alignment of the element. CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType); CharUnits eltAlign = - getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); + getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); if (hasBPFPreserveStaticOffset(Base)) addr = wrapWithBPFPreserveStaticOffset(CGF, addr); @@ -4054,19 +4043,19 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, auto LastIndex = dyn_cast(indices.back()); if (!LastIndex || (!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) { - addr = emitArraySubscriptGEP(CGF, addr, indices, - CGF.ConvertTypeForMem(eltType), inbounds, - signedIndices, loc, eltAlign, name); - return addr; + eltPtr = emitArraySubscriptGEP( + CGF, addr.getElementType(), addr.getPointer(), indices, inbounds, + signedIndices, loc, name); } else { // Remember the original array subscript for bpf target unsigned idx = LastIndex->getZExtValue(); llvm::DIType *DbgInfo = nullptr; if (arrayType) DbgInfo = CGF.getDebugInfo()->getOrCreateStandaloneType(*arrayType, loc); - eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex( - addr.getElementType(), addr.emitRawPointer(CGF), indices.size() - 1, - idx, DbgInfo); + eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getElementType(), + addr.getPointer(), + indices.size() - 1, + idx, DbgInfo); } return Address(eltPtr, CGF.ConvertTypeForMem(eltType), eltAlign); @@ -4235,8 +4224,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, CharUnits EltAlign = getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); llvm::Value *EltPtr = - emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this), - ScaledIdx, false, SignedIndices, E->getExprLoc()); + emitArraySubscriptGEP(*this, Int8Ty, Addr.getPointer(), ScaledIdx, + false, SignedIndices, E->getExprLoc()); Addr = Address(EltPtr, OrigBaseElemTy, EltAlign); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the @@ -4282,7 +4271,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, llvm::Type *CountTy = ConvertType(CountFD->getType()); llvm::Value *Res = Builder.CreateInBoundsGEP( - Int8Ty, Addr.emitRawPointer(*this), + Int8Ty, Addr.getPointer(), Builder.getInt32(OffsetDiff.getQuantity()), ".counted_by.gep"); Res = Builder.CreateAlignedLoad(CountTy, Res, getIntAlign(), ".counted_by.load"); @@ -4528,9 +4517,9 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, BaseInfo = ArrayLV.getBaseInfo(); TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); } else { - Address Base = - emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy, - ResultExprTy, IsLowerBound); + Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, + TBAAInfo, BaseTy, ResultExprTy, + IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*signedIndices=*/false, E->getExprLoc()); @@ -4617,7 +4606,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { SkippedChecks.set(SanitizerKind::Alignment, true); if (IsBaseCXXThis || isa(BaseExpr)) SkippedChecks.set(SanitizerKind::Null, true); - EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr, PtrTy, + EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); } else @@ -4666,8 +4655,8 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, LambdaLV = EmitLoadOfReferenceLValue(AddrOfExplicitObject, D->getType(), AlignmentSource::Decl); else - LambdaLV = MakeAddrLValue(AddrOfExplicitObject, - D->getType().getNonReferenceType()); + LambdaLV = MakeNaturalAlignAddrLValue(AddrOfExplicitObject.getPointer(), + D->getType().getNonReferenceType()); } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); @@ -4857,8 +4846,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // information provided by invariant.group. This is because accessing // fields may leak the real address of dynamic object, which could result // in miscompilation when leaked pointer would be compared. - auto *stripped = - Builder.CreateStripInvariantGroup(addr.emitRawPointer(*this)); + auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer()); addr = Address(stripped, addr.getElementType(), addr.getAlignment()); } } @@ -4877,11 +4865,10 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // Remember the original union field index llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(base.getType(), rec->getLocation()); - addr = - Address(Builder.CreatePreserveUnionAccessIndex( - addr.emitRawPointer(*this), - getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), - addr.getElementType(), addr.getAlignment()); + addr = Address( + Builder.CreatePreserveUnionAccessIndex( + addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), + addr.getElementType(), addr.getAlignment()); } if (FieldType->isReferenceType()) @@ -5118,9 +5105,11 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue( if (Info.LHS && Info.RHS) { Address lhsAddr = Info.LHS->getAddress(*this); Address rhsAddr = Info.RHS->getAddress(*this); - Address result = mergeAddressesInConditionalExpr( - lhsAddr, rhsAddr, Info.lhsBlock, Info.rhsBlock, - Builder.GetInsertBlock(), expr->getType()); + llvm::PHINode *phi = Builder.CreatePHI(lhsAddr.getType(), 2, "cond-lvalue"); + phi->addIncoming(lhsAddr.getPointer(), Info.lhsBlock); + phi->addIncoming(rhsAddr.getPointer(), Info.rhsBlock); + Address result(phi, lhsAddr.getElementType(), + std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment())); AlignmentSource alignSource = std::max(Info.LHS->getBaseInfo().getAlignmentSource(), Info.RHS->getBaseInfo().getAlignmentSource()); @@ -5207,7 +5196,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { LValue LV = EmitLValue(E->getSubExpr()); Address V = LV.getAddress(*this); const auto *DCE = cast(E); - return MakeNaturalAlignRawAddrLValue(EmitDynamicCast(V, DCE), E->getType()); + return MakeNaturalAlignAddrLValue(EmitDynamicCast(V, DCE), E->getType()); } case CK_ConstructorConversion: @@ -5272,8 +5261,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is // performed and the object is not of the derived type. if (sanitizePerformTypeCheck()) - EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), Derived, - E->getType()); + EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), + Derived.getPointer(), E->getType()); if (SanOpts.has(SanitizerKind::CFIDerivedCast)) EmitVTablePtrCheckForCast(E->getType(), Derived, @@ -5629,7 +5618,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { LValue CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) { - return MakeNaturalAlignRawAddrLValue(EmitCXXTypeidExpr(E), E->getType()); + return MakeNaturalAlignAddrLValue(EmitCXXTypeidExpr(E), E->getType()); } Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) { diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 143855aa84ca..5190b22bcc16 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -294,10 +294,10 @@ void AggExprEmitter::withReturnValueSlot( // Otherwise, EmitCall will emit its own, notice that it's "unused", and end // its lifetime before we have the chance to emit a proper destructor call. bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() || - (RequiresDestruction && Dest.isIgnored()); + (RequiresDestruction && !Dest.getAddress().isValid()); Address RetAddr = Address::invalid(); - RawAddress RetAllocaAddr = RawAddress::invalid(); + Address RetAllocaAddr = Address::invalid(); EHScopeStack::stable_iterator LifetimeEndBlock; llvm::Value *LifetimeSizePtr = nullptr; @@ -329,8 +329,7 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) return; - assert(Dest.isIgnored() || Dest.emitRawPointer(CGF) != - Src.getAggregatePointer(E->getType(), CGF)); + assert(Dest.isIgnored() || Dest.getPointer() != Src.getAggregatePointer()); EmitFinalDestCopy(E->getType(), Src); if (!RequiresDestruction && LifetimeStartInst) { @@ -449,8 +448,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); llvm::Value *IdxStart[] = { Zero, Zero }; llvm::Value *ArrayStart = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxStart, - "arraystart"); + ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxStart, "arraystart"); CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); ++Field; @@ -467,8 +465,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { // End pointer. llvm::Value *IdxEnd[] = { Zero, Size }; llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd, - "arrayend"); + ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxEnd, "arrayend"); CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { // Length. @@ -519,9 +516,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, // down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = { zero, zero }; - llvm::Value *begin = Builder.CreateInBoundsGEP(DestPtr.getElementType(), - DestPtr.emitRawPointer(CGF), - indices, "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP( + DestPtr.getElementType(), DestPtr.getPointer(), indices, + "arrayinit.begin"); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); CharUnits elementAlign = @@ -1062,7 +1059,7 @@ void AggExprEmitter::VisitBinCmp(const BinaryOperator *E) { if (RV.isScalar()) return {RV.getScalarVal(), nullptr}; if (RV.isAggregate()) - return {RV.getAggregatePointer(E->getType(), CGF), nullptr}; + return {RV.getAggregatePointer(), nullptr}; assert(RV.isComplex()); return RV.getComplexVal(); }; @@ -1821,7 +1818,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // else, clean it up for -O0 builds and general tidiness. if (!pushedCleanup && LV.isSimple()) if (llvm::GetElementPtrInst *GEP = - dyn_cast(LV.emitRawPointer(CGF))) + dyn_cast(LV.getPointer(CGF))) if (GEP->use_empty()) GEP->eraseFromParent(); } @@ -1852,9 +1849,9 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, // destPtr is an array*. Construct an elementType* by drilling down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = {zero, zero}; - llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getElementType(), - destPtr.emitRawPointer(CGF), - indices, "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP( + destPtr.getElementType(), destPtr.getPointer(), indices, + "arrayinit.begin"); // Prepare to special-case multidimensional array initialization: we avoid // emitting multiple destructor loops in that case. diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 5c16a48d3ee6..35da0f1a89bc 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -280,8 +280,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); - This = MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(), - BaseInfo, TBAAInfo); + This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); } else { This = EmitLValue(Base); } @@ -354,8 +353,10 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (IsImplicitObjectCXXThis || isa(IOA)) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, This, - C.getRecordType(CalleeDecl->getParent()), SkippedChecks); + EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, + This.getPointer(*this), + C.getRecordType(CalleeDecl->getParent()), + /*Alignment=*/CharUnits::Zero(), SkippedChecks); // C++ [class.virtual]p12: // Explicit qualification with the scope operator (5.1) suppresses the @@ -454,7 +455,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, else This = EmitLValue(BaseExpr, KnownNonNull).getAddress(*this); - EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), + EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(), QualType(MPT->getClass(), 0)); // Get the member function pointer. @@ -1108,10 +1109,9 @@ void CodeGenFunction::EmitNewArrayInitializer( // alloca. EndOfInit = CreateTempAlloca(BeginPtr.getType(), getPointerAlign(), "array.init.end"); - CleanupDominator = - Builder.CreateStore(BeginPtr.emitRawPointer(*this), EndOfInit); - pushIrregularPartialArrayCleanup(BeginPtr.emitRawPointer(*this), - EndOfInit, ElementType, ElementAlign, + CleanupDominator = Builder.CreateStore(BeginPtr.getPointer(), EndOfInit); + pushIrregularPartialArrayCleanup(BeginPtr.getPointer(), EndOfInit, + ElementType, ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); } @@ -1123,17 +1123,16 @@ void CodeGenFunction::EmitNewArrayInitializer( // element. TODO: some of these stores can be trivially // observed to be unnecessary. if (EndOfInit.isValid()) { - Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); + Builder.CreateStore(CurPtr.getPointer(), EndOfInit); } // FIXME: If the last initializer is an incomplete initializer list for // an array, and we have an array filler, we can fold together the two // initialization loops. StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr, AggValueSlot::DoesNotOverlap); - CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(), - CurPtr.emitRawPointer(*this), - Builder.getSize(1), - "array.exp.next"), + CurPtr = Address(Builder.CreateInBoundsGEP( + CurPtr.getElementType(), CurPtr.getPointer(), + Builder.getSize(1), "array.exp.next"), CurPtr.getElementType(), StartAlign.alignmentAtOffset((++i) * ElementSize)); } @@ -1187,7 +1186,7 @@ void CodeGenFunction::EmitNewArrayInitializer( // FIXME: Share this cleanup with the constructor call emission rather than // having it create a cleanup of its own. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); + Builder.CreateStore(CurPtr.getPointer(), EndOfInit); // Emit a constructor call loop to initialize the remaining elements. if (InitListElements) @@ -1250,15 +1249,15 @@ void CodeGenFunction::EmitNewArrayInitializer( llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end"); // Find the end of the array, hoisted out of the loop. - llvm::Value *EndPtr = Builder.CreateInBoundsGEP( - BeginPtr.getElementType(), BeginPtr.emitRawPointer(*this), NumElements, - "array.end"); + llvm::Value *EndPtr = + Builder.CreateInBoundsGEP(BeginPtr.getElementType(), BeginPtr.getPointer(), + NumElements, "array.end"); // If the number of elements isn't constant, we have to now check if there is // anything left to initialize. if (!ConstNum) { - llvm::Value *IsEmpty = Builder.CreateICmpEQ(CurPtr.emitRawPointer(*this), - EndPtr, "array.isempty"); + llvm::Value *IsEmpty = + Builder.CreateICmpEQ(CurPtr.getPointer(), EndPtr, "array.isempty"); Builder.CreateCondBr(IsEmpty, ContBB, LoopBB); } @@ -1268,20 +1267,19 @@ void CodeGenFunction::EmitNewArrayInitializer( // Set up the current-element phi. llvm::PHINode *CurPtrPhi = Builder.CreatePHI(CurPtr.getType(), 2, "array.cur"); - CurPtrPhi->addIncoming(CurPtr.emitRawPointer(*this), EntryBB); + CurPtrPhi->addIncoming(CurPtr.getPointer(), EntryBB); CurPtr = Address(CurPtrPhi, CurPtr.getElementType(), ElementAlign); // Store the new Cleanup position for irregular Cleanups. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); + Builder.CreateStore(CurPtr.getPointer(), EndOfInit); // Enter a partial-destruction Cleanup if necessary. if (!CleanupDominator && needsEHCleanup(DtorKind)) { - llvm::Value *BeginPtrRaw = BeginPtr.emitRawPointer(*this); - llvm::Value *CurPtrRaw = CurPtr.emitRawPointer(*this); - pushRegularPartialArrayCleanup(BeginPtrRaw, CurPtrRaw, ElementType, - ElementAlign, getDestroyer(DtorKind)); + pushRegularPartialArrayCleanup(BeginPtr.getPointer(), CurPtr.getPointer(), + ElementType, ElementAlign, + getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); CleanupDominator = Builder.CreateUnreachable(); } @@ -1297,8 +1295,9 @@ void CodeGenFunction::EmitNewArrayInitializer( } // Advance to the next element by adjusting the pointer type as necessary. - llvm::Value *NextPtr = Builder.CreateConstInBoundsGEP1_32( - ElementTy, CurPtr.emitRawPointer(*this), 1, "array.next"); + llvm::Value *NextPtr = + Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr.getPointer(), 1, + "array.next"); // Check whether we've gotten to the end of the array and, if so, // exit the loop. @@ -1524,9 +1523,14 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, typedef CallDeleteDuringNew DirectCleanup; - DirectCleanup *Cleanup = CGF.EHStack.pushCleanupWithExtra( - EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(), - NewPtr.emitRawPointer(CGF), AllocSize, E->passAlignment(), AllocAlign); + DirectCleanup *Cleanup = CGF.EHStack + .pushCleanupWithExtra(EHCleanup, + E->getNumPlacementArgs(), + E->getOperatorDelete(), + NewPtr.getPointer(), + AllocSize, + E->passAlignment(), + AllocAlign); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { auto &Arg = NewArgs[I + NumNonPlacementArgs]; Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty); @@ -1537,7 +1541,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, // Otherwise, we need to save all this stuff. DominatingValue::saved_type SavedNewPtr = - DominatingValue::save(CGF, RValue::get(NewPtr, CGF)); + DominatingValue::save(CGF, RValue::get(NewPtr.getPointer())); DominatingValue::saved_type SavedAllocSize = DominatingValue::save(CGF, RValue::get(AllocSize)); @@ -1614,14 +1618,14 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // In these cases, discard the computed alignment and use the // formal alignment of the allocated type. if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl) - allocation.setAlignment(allocAlign); + allocation = allocation.withAlignment(allocAlign); // Set up allocatorArgs for the call to operator delete if it's not // the reserved global operator. if (E->getOperatorDelete() && !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType()); - allocatorArgs.add(RValue::get(allocation, *this), arg->getType()); + allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType()); } } else { @@ -1709,7 +1713,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull"); contBB = createBasicBlock("new.cont"); - llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull"); + llvm::Value *isNull = + Builder.CreateIsNull(allocation.getPointer(), "new.isnull"); Builder.CreateCondBr(isNull, contBB, notNullBB); EmitBlock(notNullBB); } @@ -1755,12 +1760,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { SkippedChecks.set(SanitizerKind::Null, nullCheck); EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(), - result, allocType, result.getAlignment(), SkippedChecks, - numElements); + result.getPointer(), allocType, result.getAlignment(), + SkippedChecks, numElements); EmitNewInitializer(*this, E, allocType, elementTy, result, numElements, allocSizeWithoutCookie); - llvm::Value *resultPtr = result.emitRawPointer(*this); + llvm::Value *resultPtr = result.getPointer(); if (E->isArray()) { // NewPtr is a pointer to the base element type. If we're // allocating an array of arrays, we'll need to cast back to the @@ -1904,8 +1909,7 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, Dtor); else - CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.emitRawPointer(CGF), - ElementType); + CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType); } /// Emit the code for deleting a single object. @@ -1921,7 +1925,8 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // dynamic type, the static type shall be a base class of the dynamic type // of the object to be deleted and the static type shall have a virtual // destructor or the behavior is undefined. - CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, DE->getExprLoc(), Ptr, + CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, + DE->getExprLoc(), Ptr.getPointer(), ElementType); const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); @@ -1970,8 +1975,9 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // Make sure that we call delete even if the dtor throws. // This doesn't have to a conditional cleanup because we're going // to pop it off in a second. - CGF.EHStack.pushCleanup( - NormalAndEHCleanup, Ptr.emitRawPointer(CGF), OperatorDelete, ElementType); + CGF.EHStack.pushCleanup(NormalAndEHCleanup, + Ptr.getPointer(), + OperatorDelete, ElementType); if (Dtor) CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, @@ -2058,7 +2064,7 @@ static void EmitArrayDelete(CodeGenFunction &CGF, CharUnits elementAlign = deletedPtr.getAlignment().alignmentOfArrayElement(elementSize); - llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF); + llvm::Value *arrayBegin = deletedPtr.getPointer(); llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP( deletedPtr.getElementType(), arrayBegin, numElements, "delete.end"); @@ -2089,7 +2095,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); - llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull"); + llvm::Value *IsNull = Builder.CreateIsNull(Ptr.getPointer(), "isnull"); Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); @@ -2124,8 +2130,10 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { GEP.push_back(Zero); } - Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, ConvertTypeForMem(DeleteTy), - Ptr.getAlignment(), "del.first"); + Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getElementType(), + Ptr.getPointer(), GEP, "del.first"), + ConvertTypeForMem(DeleteTy), Ptr.getAlignment(), + Ptr.isKnownNonNull()); } assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); @@ -2183,7 +2191,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, // destruction and the static type of the operand is neither the constructor // or destructor’s class nor one of its bases, the behavior is undefined. CGF.EmitTypeCheck(CodeGenFunction::TCK_DynamicOperation, E->getExprLoc(), - ThisPtr, SrcRecordTy); + ThisPtr.getPointer(), SrcRecordTy); // C++ [expr.typeid]p2: // If the glvalue expression is obtained by applying the unary * operator to @@ -2199,7 +2207,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, CGF.createBasicBlock("typeid.bad_typeid"); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end"); - llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr); + llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr.getPointer()); CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock); CGF.EmitBlock(BadTypeidBlock); @@ -2285,7 +2293,8 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, // construction or destruction and the static type of the operand is not a // pointer to or object of the constructor or destructor’s own class or one // of its bases, the dynamic_cast results in undefined behavior. - EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr, SrcRecordTy); + EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr.getPointer(), + SrcRecordTy); if (DCE->isAlwaysNull()) { if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy)) { @@ -2320,7 +2329,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, CastNull = createBasicBlock("dynamic_cast.null"); CastNotNull = createBasicBlock("dynamic_cast.notnull"); - llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr); + llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr.getPointer()); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 36d7493d9a6b..67a3cdc77042 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -800,8 +800,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, // Add a vtable pointer, if we need one and it hasn't already been added. if (Layout.hasOwnVFPtr()) { llvm::Constant *VTableAddressPoint = - CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset), - VTableClass); + CGM.getCXXABI().getVTableAddressPointForConstExpr( + BaseSubobject(CD, Offset), VTableClass); if (!AppendBytes(Offset, VTableAddressPoint)) return false; } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 83247aa48f86..8536570087ad 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2250,7 +2250,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { // performed and the object is not of the derived type. if (CGF.sanitizePerformTypeCheck()) CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(), - Derived, DestTy->getPointeeType()); + Derived.getPointer(), DestTy->getPointeeType()); if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast)) CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived, @@ -2258,14 +2258,13 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { CodeGenFunction::CFITCK_DerivedCast, CE->getBeginLoc()); - return CGF.getAsNaturalPointerTo(Derived, CE->getType()->getPointeeType()); + return Derived.getPointer(); } case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { // The EmitPointerWithAlignment path does this fine; just discard // the alignment. - return CGF.getAsNaturalPointerTo(CGF.EmitPointerWithAlignment(CE), - CE->getType()->getPointeeType()); + return CGF.EmitPointerWithAlignment(CE).getPointer(); } case CK_Dynamic: { @@ -2275,8 +2274,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } case CK_ArrayToPointerDecay: - return CGF.getAsNaturalPointerTo(CGF.EmitArrayToPointerDecay(E), - CE->getType()->getPointeeType()); + return CGF.EmitArrayToPointerDecay(E).getPointer(); case CK_FunctionToPointerDecay: return EmitLValue(E).getPointer(CGF); @@ -5590,16 +5588,3 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr, return GEPVal; } - -Address CodeGenFunction::EmitCheckedInBoundsGEP( - Address Addr, ArrayRef IdxList, llvm::Type *elementType, - bool SignedIndices, bool IsSubtraction, SourceLocation Loc, CharUnits Align, - const Twine &Name) { - if (!SanOpts.has(SanitizerKind::PointerOverflow)) - return Builder.CreateInBoundsGEP(Addr, IdxList, elementType, Align, Name); - - return RawAddress( - EmitCheckedInBoundsGEP(Addr.getElementType(), Addr.emitRawPointer(*this), - IdxList, SignedIndices, IsSubtraction, Loc, Name), - elementType, Align); -} diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 8fade0fac21e..75c1d7fbea84 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -366,7 +366,7 @@ template struct GenFuncBase { llvm::Value *SizeInBytes = CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP( - CGF.Int8Ty, DstAddr.emitRawPointer(CGF), SizeInBytes); + CGF.Int8Ty, DstAddr.getPointer(), SizeInBytes); llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); // Create the header block and insert the phi instructions. @@ -376,7 +376,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); - PHIs[I]->addIncoming(StartAddrs[I].emitRawPointer(CGF), PreheaderBB); + PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); } // Create the exit and loop body blocks. @@ -410,7 +410,7 @@ template struct GenFuncBase { // Instrs to update the destination and source addresses. // Update phi instructions. NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); - PHIs[I]->addIncoming(NewAddrs[I].emitRawPointer(CGF), LoopBB); + PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); } // Insert an unconditional branch to the header block. @@ -488,7 +488,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { Alignments[I] = Addrs[I].getAlignment(); - Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF); + Ptrs[I] = Addrs[I].getPointer(); } if (llvm::Function *F = diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index c7f497a7c845..f3a948cf13f9 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -94,8 +94,8 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { // and cast value to correct type Address Temporary = CreateMemTemp(SubExpr->getType()); EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); - llvm::Value *BitCast = Builder.CreateBitCast( - Temporary.emitRawPointer(*this), ConvertType(ArgQT)); + llvm::Value *BitCast = + Builder.CreateBitCast(Temporary.getPointer(), ConvertType(ArgQT)); Args.add(RValue::get(BitCast), ArgQT); // Create char array to store type encoding @@ -204,11 +204,11 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); const ParmVarDecl *argDecl = *PI++; QualType ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Objects, *this), ArgQT); + Args.add(RValue::get(Objects.getPointer()), ArgQT); if (DLE) { argDecl = *PI++; ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Keys, *this), ArgQT); + Args.add(RValue::get(Keys.getPointer()), ArgQT); } argDecl = *PI; ArgQT = argDecl->getType().getUnqualifiedType(); @@ -827,7 +827,7 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, // sizeof (Type of Ivar), isAtomic, false); CallArgList args; - llvm::Value *dest = CGF.ReturnValue.emitRawPointer(CGF); + llvm::Value *dest = CGF.ReturnValue.getPointer(); args.add(RValue::get(dest), Context.VoidPtrTy); args.add(RValue::get(src), Context.VoidPtrTy); @@ -1147,8 +1147,8 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, callCStructCopyConstructor(Dst, Src); } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), - ivar, AtomicHelperFn); + emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), ivar, + AtomicHelperFn); } return; } @@ -1163,7 +1163,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), + emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), ivar, AtomicHelperFn); } return; @@ -1287,7 +1287,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { - value = LV.getAddress(*this).emitRawPointer(*this); + value = LV.getAddress(*this).getPointer(); } else { // We want to load and autoreleaseReturnValue ARC __weak ivars. if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { @@ -1821,14 +1821,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ CallArgList Args; // The first argument is a temporary of the enumeration-state type. - Args.add(RValue::get(StatePtr, *this), getContext().getPointerType(StateTy)); + Args.add(RValue::get(StatePtr.getPointer()), + getContext().getPointerType(StateTy)); // The second argument is a temporary array with space for NumItems // pointers. We'll actually be loading elements from the array // pointer written into the control state; this buffer is so that // collections that *aren't* backed by arrays can still queue up // batches of elements. - Args.add(RValue::get(ItemsPtr, *this), getContext().getPointerType(ItemsTy)); + Args.add(RValue::get(ItemsPtr.getPointer()), + getContext().getPointerType(ItemsTy)); // The third argument is the capacity of that temporary array. llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType()); @@ -2196,7 +2198,7 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr, if (!fn) fn = getARCIntrinsic(IntID, CGF.CGM); - return CGF.EmitNounwindRuntimeCall(fn, addr.emitRawPointer(CGF)); + return CGF.EmitNounwindRuntimeCall(fn, addr.getPointer()); } /// Perform an operation having the following signature: @@ -2214,8 +2216,9 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr, llvm::Type *origType = value->getType(); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(addr.emitRawPointer(CGF), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy)}; + CGF.Builder.CreateBitCast(addr.getPointer(), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy) + }; llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2234,8 +2237,9 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src, fn = getARCIntrinsic(IntID, CGF.CGM); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(src.emitRawPointer(CGF), CGF.Int8PtrPtrTy)}; + CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(src.getPointer(), CGF.Int8PtrPtrTy) + }; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2486,8 +2490,9 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr, fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM); llvm::Value *args[] = { - Builder.CreateBitCast(addr.emitRawPointer(*this), Int8PtrPtrTy), - Builder.CreateBitCast(value, Int8PtrTy)}; + Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy), + Builder.CreateBitCast(value, Int8PtrTy) + }; EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2638,7 +2643,7 @@ void CodeGenFunction::EmitARCDestroyWeak(Address addr) { if (!fn) fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM); - EmitNounwindRuntimeCall(fn, addr.emitRawPointer(*this)); + EmitNounwindRuntimeCall(fn, addr.getPointer()); } /// void \@objc_moveWeak(i8** %dest, i8** %src) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 4e7f777ba1d9..a36b0cdddaf0 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -706,8 +706,7 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), - cmd}; + EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -762,8 +761,8 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::FunctionCallee LookupFn = SlotLookupFn; // Store the receiver on the stack so that we can reload it later - RawAddress ReceiverPtr = - CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); + Address ReceiverPtr = + CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); Builder.CreateStore(Receiver, ReceiverPtr); llvm::Value *self; @@ -779,9 +778,9 @@ class CGObjCGNUstep : public CGObjCGNU { LookupFn2->addParamAttr(0, llvm::Attribute::NoCapture); llvm::Value *args[] = { - EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy)}; + EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy) }; llvm::CallBase *slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args); slot->setOnlyReadsMemory(); slot->setMetadata(msgSendMDKind, node); @@ -801,7 +800,7 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {ObjCSuper.emitRawPointer(CGF), cmd}; + llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd}; llvm::CallInst *slot = CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs); @@ -1222,10 +1221,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { llvm::Value *cmd, MessageSendInfo &MSI) override { // Don't access the slot unless we're trying to cache the result. CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = { - CGObjCGNU::EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), - PtrToObjCSuperTy), - cmd}; + llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, + ObjCSuper.getPointer(), + PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -2187,8 +2186,7 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), - cmd, + EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd, }; if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) @@ -4203,15 +4201,15 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF, Address AddrWeakObj) { CGBuilderTy &B = CGF.Builder; - return B.CreateCall( - WeakReadFn, EnforceType(B, AddrWeakObj.emitRawPointer(CGF), PtrToIdTy)); + return B.CreateCall(WeakReadFn, + EnforceType(B, AddrWeakObj.getPointer(), PtrToIdTy)); } void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); B.CreateCall(WeakAssignFn, {src, dstVal}); } @@ -4220,7 +4218,7 @@ void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF, bool threadlocal) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); // FIXME. Add threadloca assign API assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI"); B.CreateCall(GlobalAssignFn, {src, dstVal}); @@ -4231,7 +4229,7 @@ void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *ivarOffset) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), IdTy); + llvm::Value *dstVal = EnforceType(B, dst.getPointer(), IdTy); B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset}); } @@ -4239,7 +4237,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); B.CreateCall(StrongCastAssignFn, {src, dstVal}); } @@ -4248,8 +4246,8 @@ void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address SrcPtr, llvm::Value *Size) { CGBuilderTy &B = CGF.Builder; - llvm::Value *DestPtrVal = EnforceType(B, DestPtr.emitRawPointer(CGF), PtrTy); - llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.emitRawPointer(CGF), PtrTy); + llvm::Value *DestPtrVal = EnforceType(B, DestPtr.getPointer(), PtrTy); + llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.getPointer(), PtrTy); B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal, Size}); } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 8a599c10e1ca..ed8d7b9a065d 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1310,7 +1310,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - ConstantAddress EmitSelectorAddr(Selector Sel); + Address EmitSelectorAddr(Selector Sel); public: CGObjCMac(CodeGen::CodeGenModule &cgm); @@ -1538,7 +1538,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - ConstantAddress EmitSelectorAddr(Selector Sel); + Address EmitSelectorAddr(Selector Sel); /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C /// interface. The return value has type EHTypePtrTy. @@ -2064,8 +2064,9 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, const ObjCMethodDecl *Method) { // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - RawAddress ObjCSuper = CGF.CreateTempAlloca( - ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); + Address ObjCSuper = + CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), + "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, @@ -4258,7 +4259,7 @@ namespace { CGF.EmitBlock(FinallyCallExit); CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), - ExceptionData.emitRawPointer(CGF)); + ExceptionData.getPointer()); CGF.EmitBlock(FinallyNoCallExit); @@ -4424,9 +4425,7 @@ void FragileHazards::emitHazardsInNewBlocks() { } static void addIfPresent(llvm::DenseSet &S, Address V) { - if (V.isValid()) - if (llvm::Value *Ptr = V.getBasePointer()) - S.insert(Ptr); + if (V.isValid()) S.insert(V.getPointer()); } void FragileHazards::collectLocals() { @@ -4629,13 +4628,13 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // - Call objc_exception_try_enter to push ExceptionData on top of // the EH stack. CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.emitRawPointer(CGF)); + ExceptionData.getPointer()); // - Call setjmp on the exception data buffer. llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( - ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes, + ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes, "setjmp_buffer"); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); @@ -4674,9 +4673,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, } else { // Retrieve the exception object. We may emit multiple blocks but // nothing can cross this so the value is already in SSA form. - llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( - ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), - "caught"); + llvm::CallInst *Caught = + CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), + ExceptionData.getPointer(), "caught"); // Push the exception to rethrow onto the EH value stack for the // benefit of any @throws in the handlers. @@ -4699,7 +4698,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Enter a new exception try block (in case a @catch block // throws an exception). CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.emitRawPointer(CGF)); + ExceptionData.getPointer()); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), @@ -4830,9 +4829,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Extract the new exception and save it to the // propagating-exception slot. assert(PropagatingExnVar.isValid()); - llvm::CallInst *NewCaught = CGF.EmitNounwindRuntimeCall( - ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), - "caught"); + llvm::CallInst *NewCaught = + CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), + ExceptionData.getPointer(), "caught"); CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); // Don't pop the catch handler; the throw already did. @@ -4862,8 +4861,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Otherwise, just look in the buffer for the exception to throw. } else { - llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( - ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF)); + llvm::CallInst *Caught = + CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), + ExceptionData.getPointer()); PropagatingExn = Caught; } @@ -4906,7 +4906,7 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, Address AddrWeakObj) { llvm::Type* DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -4928,8 +4928,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = { src, dstVal }; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -4950,8 +4950,8 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), @@ -4977,8 +4977,8 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -4997,8 +4997,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "strongassign"); @@ -5007,8 +5007,7 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *size) { - llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), - SrcPtr.emitRawPointer(CGF), size}; + llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size }; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -5244,7 +5243,7 @@ llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel)); } -ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) { +Address CGObjCMac::EmitSelectorAddr(Selector Sel) { CharUnits Align = CGM.getPointerAlign(); llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; @@ -5255,7 +5254,7 @@ ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) { Entry->setExternallyInitialized(true); } - return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); + return Address(Entry, ObjCTypes.SelectorPtrTy, Align); } llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { @@ -7324,7 +7323,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, ObjCTypes.MessageRefTy, CGF.getPointerAlign()); // Update the message ref argument. - args[1].setRValue(RValue::get(mref, CGF)); + args[1].setRValue(RValue::get(mref.getPointer())); // Load the function to call from the message ref table. Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0); @@ -7553,8 +7552,9 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // ... // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - RawAddress ObjCSuper = CGF.CreateTempAlloca( - ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); + Address ObjCSuper = + CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), + "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); @@ -7594,7 +7594,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, return LI; } -ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { +Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; CharUnits Align = CGM.getPointerAlign(); if (!Entry) { @@ -7610,7 +7610,7 @@ ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { CGM.addCompilerUsedGlobal(Entry); } - return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); + return Address(Entry, ObjCTypes.SelectorPtrTy, Align); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. @@ -7629,8 +7629,8 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -7650,8 +7650,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "weakassign"); @@ -7660,8 +7660,7 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *Size) { - llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), - SrcPtr.emitRawPointer(CGF), Size}; + llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size }; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -7673,7 +7672,7 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( Address AddrWeakObj) { llvm::Type *DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -7695,8 +7694,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -7717,8 +7716,8 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), - ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = + CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 01d0f35da196..424564f97599 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -67,7 +67,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr"); if (!Ivar->isBitField()) { - LValue LV = CGF.MakeNaturalAlignRawAddrLValue(V, IvarTy); + LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); return LV; } @@ -233,7 +233,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI(); if (auto *CPI = dyn_cast_or_null(CPICandidate)) { CGF.CurrentFuncletPad = CPI; - CPI->setOperand(2, CGF.getExceptionSlot().emitRawPointer(CGF)); + CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); CGF.EHStack.pushCleanup(NormalCleanup, CPI); } } @@ -405,7 +405,7 @@ bool CGObjCRuntime::canMessageReceiverBeNull(CodeGenFunction &CGF, auto self = curMethod->getSelfDecl(); if (self->getType().isConstQualified()) { if (auto LI = dyn_cast(receiver->stripPointerCasts())) { - llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).emitRawPointer(CGF); + llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).getPointer(); if (selfAddr == LI->getPointerOperand()) { return false; } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index bc363313dec6..00e395c2a207 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -622,7 +622,7 @@ static void emitInitWithReductionInitializer(CodeGenFunction &CGF, auto *GV = new llvm::GlobalVariable( CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Init, Name); - LValue LV = CGF.MakeNaturalAlignRawAddrLValue(GV, Ty); + LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); RValue InitRVal; switch (CGF.getEvaluationKind(Ty)) { case TEK_Scalar: @@ -668,8 +668,8 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, llvm::Value *SrcBegin = nullptr; if (DRD) - SrcBegin = SrcAddr.emitRawPointer(CGF); - llvm::Value *DestBegin = DestAddr.emitRawPointer(CGF); + SrcBegin = SrcAddr.getPointer(); + llvm::Value *DestBegin = DestAddr.getPointer(); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -912,7 +912,7 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr) { - RawAddress Tmp = RawAddress::invalid(); + Address Tmp = Address::invalid(); Address TopTmp = Address::invalid(); Address MostTopTmp = Address::invalid(); BaseTy = BaseTy.getNonReferenceType(); @@ -971,10 +971,10 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( SharedAddr.getElementType(), BaseLValue.getPointer(CGF), - SharedAddr.emitRawPointer(CGF)); + SharedAddr.getPointer()); llvm::Value *PrivatePointer = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivateAddr.emitRawPointer(CGF), SharedAddr.getType()); + PrivateAddr.getPointer(), SharedAddr.getType()); llvm::Value *Ptr = CGF.Builder.CreateGEP( SharedAddr.getElementType(), PrivatePointer, Adjustment); return castToBase(CGF, OrigVD->getType(), @@ -1557,7 +1557,7 @@ static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc( return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName); } -ConstantAddress CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { +Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; auto LinkageForVariable = [&VD, this]() { @@ -1579,8 +1579,8 @@ ConstantAddress CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { LinkageForVariable); if (!addr) - return ConstantAddress::invalid(); - return ConstantAddress(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); + return Address::invalid(); + return Address(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); } llvm::Constant * @@ -1604,7 +1604,7 @@ Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy), + CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy), CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), getOrCreateThreadPrivateCache(VD)}; return Address( @@ -1627,8 +1627,7 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit( // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) // to register constructor/destructor for variable. llvm::Value *Args[] = { - OMPLoc, - CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.VoidPtrTy), + OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), Ctor, CopyCtor, Dtor}; CGF.EmitRuntimeCall( OMPBuilder.getOrCreateRuntimeFunction( @@ -1901,13 +1900,13 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, // OutlinedFn(>id, &zero_bound, CapturedStruct); Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); - RawAddress ZeroAddrBound = + Address ZeroAddrBound = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".bound.zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddrBound); llvm::SmallVector OutlinedFnArgs; // ThreadId for serialized parallels is 0. - OutlinedFnArgs.push_back(ThreadIDAddr.emitRawPointer(CGF)); + OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); @@ -2273,7 +2272,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, emitUpdateLocation(CGF, Loc), // ident_t * getThreadID(CGF, Loc), // i32 BufSize, // size_t - CL.emitRawPointer(CGF), // void * + CL.getPointer(), // void * CpyFn, // void (*) (void *, void *) DidItVal // i32 did_it }; @@ -2592,10 +2591,10 @@ static void emitForStaticInitCall( ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, M2)), // Schedule type - Values.IL.emitRawPointer(CGF), // &isLastIter - Values.LB.emitRawPointer(CGF), // &LB - Values.UB.emitRawPointer(CGF), // &UB - Values.ST.emitRawPointer(CGF), // &Stride + Values.IL.getPointer(), // &isLastIter + Values.LB.getPointer(), // &LB + Values.UB.getPointer(), // &UB + Values.ST.getPointer(), // &Stride CGF.Builder.getIntN(Values.IVSize, 1), // Incr Chunk // Chunk }; @@ -2698,11 +2697,12 @@ llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, // kmp_int[32|64] *p_stride); llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - IL.emitRawPointer(CGF), // &isLastIter - LB.emitRawPointer(CGF), // &Lower - UB.emitRawPointer(CGF), // &Upper - ST.emitRawPointer(CGF) // &Stride + emitUpdateLocation(CGF, Loc), + getThreadID(CGF, Loc), + IL.getPointer(), // &isLastIter + LB.getPointer(), // &Lower + UB.getPointer(), // &Upper + ST.getPointer() // &Stride }; llvm::Value *Call = CGF.EmitRuntimeCall( OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args); @@ -3047,7 +3047,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, CGF.Builder .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF), CGF.VoidPtrTy, CGF.Int8Ty) - .emitRawPointer(CGF)}; + .getPointer()}; SmallVector CallArgs(std::begin(CommonArgs), std::end(CommonArgs)); if (isOpenMPTaskLoopDirective(Kind)) { @@ -3574,8 +3574,7 @@ getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); Address UpAddrAddress = UpAddrLVal.getAddress(CGF); llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( - UpAddrAddress.getElementType(), UpAddrAddress.emitRawPointer(CGF), - /*Idx0=*/1); + UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); @@ -3889,9 +3888,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Size; std::tie(Addr, Size) = getPointerAndSize(CGF, E); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - LValue Base = - CGF.MakeAddrLValue(CGF.Builder.CreateGEP(CGF, AffinitiesArray, Idx), - KmpTaskAffinityInfoTy); + LValue Base = CGF.MakeAddrLValue( + CGF.Builder.CreateGEP(AffinitiesArray, Idx), KmpTaskAffinityInfoTy); // affs[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); @@ -3912,7 +3910,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); llvm::Value *GTid = getThreadID(CGF, Loc); llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - AffinitiesArray.emitRawPointer(CGF), CGM.VoidPtrTy); + AffinitiesArray.getPointer(), CGM.VoidPtrTy); // FIXME: Emit the function and ignore its result for now unless the // runtime function is properly implemented. (void)CGF.EmitRuntimeCall( @@ -3923,8 +3921,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( NewTask, KmpTaskTWithPrivatesPtrTy); - LValue Base = CGF.MakeNaturalAlignRawAddrLValue(NewTaskNewTaskTTy, - KmpTaskTWithPrivatesQTy); + LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, + KmpTaskTWithPrivatesQTy); LValue TDBase = CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); // Fill the data in the resulting kmp_task_t record. @@ -4049,7 +4047,7 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, CGF.ConvertTypeForMem(KmpDependInfoPtrTy)), KmpDependInfoPtrTy->castAs()); Address DepObjAddr = CGF.Builder.CreateGEP( - CGF, Base.getAddress(CGF), + Base.getAddress(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4099,7 +4097,7 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue &PosLVal = *Pos.get(); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(CGF, DependenciesArray, Idx), KmpDependInfoTy); + CGF.Builder.CreateGEP(DependenciesArray, Idx), KmpDependInfoTy); } // deps[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( @@ -4197,7 +4195,7 @@ void CGOpenMPRuntime::emitDepobjElements(CodeGenFunction &CGF, ElSize, CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - Address DepAddr = CGF.Builder.CreateGEP(CGF, DependenciesArray, Pos); + Address DepAddr = CGF.Builder.CreateGEP(DependenciesArray, Pos); CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); // Increase pos. @@ -4432,7 +4430,7 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), CGF.ConvertTypeForMem(KmpDependInfoTy)); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getElementType(), Addr.emitRawPointer(CGF), + Addr.getElementType(), Addr.getPointer(), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, CGF.VoidPtrTy); @@ -4462,8 +4460,8 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, Address Begin = Base.getAddress(CGF); // Cast from pointer to array type to pointer to single element. - llvm::Value *End = CGF.Builder.CreateGEP(Begin.getElementType(), - Begin.emitRawPointer(CGF), NumDeps); + llvm::Value *End = CGF.Builder.CreateGEP( + Begin.getElementType(), Begin.getPointer(), NumDeps); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); @@ -4471,7 +4469,7 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, CGF.EmitBlock(BodyBB); llvm::PHINode *ElementPHI = CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); - ElementPHI->addIncoming(Begin.emitRawPointer(CGF), EntryBB); + ElementPHI->addIncoming(Begin.getPointer(), EntryBB); Begin = Begin.withPointer(ElementPHI, KnownNonNull); Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4485,12 +4483,12 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, FlagsLVal); // Shift the address forward by one element. - llvm::Value *ElementNext = - CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext") - .emitRawPointer(CGF); - ElementPHI->addIncoming(ElementNext, CGF.Builder.GetInsertBlock()); + Address ElementNext = + CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); + ElementPHI->addIncoming(ElementNext.getPointer(), + CGF.Builder.GetInsertBlock()); llvm::Value *IsEmpty = - CGF.Builder.CreateICmpEQ(ElementNext, End, "omp.isempty"); + CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); // Done. CGF.EmitBlock(DoneBB, /*IsFinished=*/true); @@ -4533,7 +4531,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepTaskArgs[1] = ThreadID; DepTaskArgs[2] = NewTask; DepTaskArgs[3] = NumOfElements; - DepTaskArgs[4] = DependenciesArray.emitRawPointer(CGF); + DepTaskArgs[4] = DependenciesArray.getPointer(); DepTaskArgs[5] = CGF.Builder.getInt32(0); DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); } @@ -4565,7 +4563,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); + DepWaitTaskArgs[3] = DependenciesArray.getPointer(); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -4727,8 +4725,8 @@ static void EmitOMPAggregateReduction( const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); - llvm::Value *RHSBegin = RHSAddr.emitRawPointer(CGF); - llvm::Value *LHSBegin = LHSAddr.emitRawPointer(CGF); + llvm::Value *RHSBegin = RHSAddr.getPointer(); + llvm::Value *LHSBegin = LHSAddr.getPointer(); // Cast from pointer to array type to pointer to single element. llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); @@ -4992,7 +4990,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, QualType ReductionArrayTy = C.getConstantArrayType( C.VoidPtrTy, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); - RawAddress ReductionList = + Address ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); const auto *IPriv = Privates.begin(); unsigned Idx = 0; @@ -5464,7 +5462,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( C.getConstantArrayType(RDType, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); // kmp_task_red_input_t .rd_input.[Size]; - RawAddress TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); + Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, Data.ReductionCopies, Data.ReductionOps); for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { @@ -5475,7 +5473,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( TaskRedInput.getElementType(), TaskRedInput.getPointer(), Idxs, /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, ".rd_input.gep."); - LValue ElemLVal = CGF.MakeNaturalAlignRawAddrLValue(GEP, RDType); + LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); // ElemLVal.reduce_shar = &Shareds[Cnt]; LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); RCG.emitSharedOrigLValue(CGF, Cnt); @@ -5631,7 +5629,7 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); + DepWaitTaskArgs[3] = DependenciesArray.getPointer(); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -5854,7 +5852,7 @@ void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, AllocatorTraitsLVal.getBaseInfo(), AllocatorTraitsLVal.getTBAAInfo()); - llvm::Value *Traits = Addr.emitRawPointer(CGF); + llvm::Value *Traits = Addr.getPointer(); llvm::Value *AllocatorVal = CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -7314,19 +7312,17 @@ private: CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) .getAddress(CGF); } - llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); - llvm::Value *LBPtr = LB.emitRawPointer(CGF); - Size = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, - LBPtr); + Size = CGF.Builder.CreatePtrDiff( + CGF.Int8Ty, ComponentLB.getPointer(), LB.getPointer()); break; } } assert(Size && "Failed to determine structure size"); CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); + CombinedInfo.BasePointers.push_back(BP.getPointer()); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); + CombinedInfo.Pointers.push_back(LB.getPointer()); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7336,14 +7332,13 @@ private: LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); } CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); + CombinedInfo.BasePointers.push_back(BP.getPointer()); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); - llvm::Value *LBPtr = LB.emitRawPointer(CGF); + CombinedInfo.Pointers.push_back(LB.getPointer()); Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF), - LBPtr); + CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).getPointer(), + LB.getPointer()); CombinedInfo.Sizes.push_back( CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7361,21 +7356,20 @@ private: (Next == CE && MapType != OMPC_MAP_unknown)) { if (!IsMappingWholeStruct) { CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); + CombinedInfo.BasePointers.push_back(BP.getPointer()); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); + CombinedInfo.Pointers.push_back(LB.getPointer()); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1); } else { StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - StructBaseCombinedInfo.BasePointers.push_back( - BP.emitRawPointer(CGF)); + StructBaseCombinedInfo.BasePointers.push_back(BP.getPointer()); StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr); StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - StructBaseCombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); + StructBaseCombinedInfo.Pointers.push_back(LB.getPointer()); StructBaseCombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); StructBaseCombinedInfo.NonContigInfo.Dims.push_back( @@ -8217,11 +8211,11 @@ public: } CombinedInfo.Exprs.push_back(VD); // Base is the base of the struct - CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); + CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); // Pointer is the address of the lowest element - llvm::Value *LB = LBAddr.emitRawPointer(CGF); + llvm::Value *LB = LBAddr.getPointer(); const CXXMethodDecl *MD = CGF.CurFuncDecl ? dyn_cast(CGF.CurFuncDecl) : nullptr; const CXXRecordDecl *RD = MD ? MD->getParent() : nullptr; @@ -8235,7 +8229,7 @@ public: // if the this[:1] expression had appeared in a map clause with a map-type // of tofrom. // Emit this[:1] - CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); + CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer()); QualType Ty = MD->getFunctionObjectParameterType(); llvm::Value *Size = CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty, @@ -8244,7 +8238,7 @@ public: } else { CombinedInfo.Pointers.push_back(LB); // Size is (addr of {highest+1} element) - (addr of lowest element) - llvm::Value *HB = HBAddr.emitRawPointer(CGF); + llvm::Value *HB = HBAddr.getPointer(); llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32( HBAddr.getElementType(), HB, /*Idx0=*/1); llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); @@ -8753,7 +8747,7 @@ public: Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( CV, ElementType, CGF.getContext().getDeclAlign(VD), AlignmentSource::Decl)); - CombinedInfo.Pointers.push_back(PtrAddr.emitRawPointer(CGF)); + CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); } else { CombinedInfo.Pointers.push_back(CV); } @@ -9564,11 +9558,10 @@ static void emitTargetCallKernelLaunch( bool HasNoWait = D.hasClausesOfKind(); unsigned NumTargetItems = InputInfo.NumberOfTargetItems; - llvm::Value *BasePointersArray = - InputInfo.BasePointersArray.emitRawPointer(CGF); - llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF); - llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF); - llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF); + llvm::Value *BasePointersArray = InputInfo.BasePointersArray.getPointer(); + llvm::Value *PointersArray = InputInfo.PointersArray.getPointer(); + llvm::Value *SizesArray = InputInfo.SizesArray.getPointer(); + llvm::Value *MappersArray = InputInfo.MappersArray.getPointer(); auto &&EmitTargetCallFallbackCB = [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS, @@ -10316,16 +10309,15 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( // Source location for the ident struct llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); - llvm::Value *OffloadingArgs[] = { - RTLoc, - DeviceID, - PointerNum, - InputInfo.BasePointersArray.emitRawPointer(CGF), - InputInfo.PointersArray.emitRawPointer(CGF), - InputInfo.SizesArray.emitRawPointer(CGF), - MapTypesArray, - MapNamesArray, - InputInfo.MappersArray.emitRawPointer(CGF)}; + llvm::Value *OffloadingArgs[] = {RTLoc, + DeviceID, + PointerNum, + InputInfo.BasePointersArray.getPointer(), + InputInfo.PointersArray.getPointer(), + InputInfo.SizesArray.getPointer(), + MapTypesArray, + MapNamesArray, + InputInfo.MappersArray.getPointer()}; // Select the right runtime function call for each standalone // directive. @@ -11136,7 +11128,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, getThreadID(CGF, D.getBeginLoc()), llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).emitRawPointer(CGF), + CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), CGM.VoidPtrTy)}; llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( @@ -11170,8 +11162,7 @@ static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, /*Volatile=*/false, Int64Ty); } llvm::Value *Args[] = { - ULoc, ThreadID, - CGF.Builder.CreateConstArrayGEP(CntAddr, 0).emitRawPointer(CGF)}; + ULoc, ThreadID, CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; llvm::FunctionCallee RTLFn; llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); OMPDoacrossKind ODK; @@ -11341,7 +11332,7 @@ Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( CGF, SourceLocation::getFromRawEncoding(LocEncoding)); Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - Addr.emitRawPointer(CGF), CGF.VoidPtrTy); + Addr.getPointer(), CGF.VoidPtrTy); llvm::Value *AllocVal = getAllocatorVal(CGF, AllocExpr); Args[2] = AllocVal; CGF.EmitRuntimeCall(RTLFn, Args); @@ -11699,17 +11690,15 @@ void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LLIVTy, getName({UniqueDeclName, "iv"})); cast(LastIV)->setAlignment( IVLVal.getAlignment().getAsAlign()); - LValue LastIVLVal = - CGF.MakeNaturalAlignRawAddrLValue(LastIV, IVLVal.getType()); + LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); // Last value of the lastprivate conditional. // decltype(priv_a) last_a; llvm::GlobalVariable *Last = OMPBuilder.getOrCreateInternalVariable( CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); - cast(Last)->setAlignment( - LVal.getAlignment().getAsAlign()); - LValue LastLVal = - CGF.MakeRawAddrLValue(Last, LVal.getType(), LVal.getAlignment()); + Last->setAlignment(LVal.getAlignment().getAsAlign()); + LValue LastLVal = CGF.MakeAddrLValue( + Address(Last, Last->getValueType(), LVal.getAlignment()), LVal.getType()); // Global loop counter. Required to handle inner parallel-for regions. // iv @@ -11882,8 +11871,9 @@ void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( // The variable was not updated in the region - exit. if (!GV) return; - LValue LPLVal = CGF.MakeRawAddrLValue( - GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); + LValue LPLVal = CGF.MakeAddrLValue( + Address(GV, GV->getValueType(), PrivLVal.getAlignment()), + PrivLVal.getType().getNonReferenceType()); llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); CGF.EmitStoreOfScalar(Res, PrivLVal); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 522ae3d35d22..c3206427b143 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1068,12 +1068,13 @@ public: /// \param Loc Location of the reference to threadprivate var. /// \return Address of the threadprivate variable for the current thread. virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, Address VDAddr, + const VarDecl *VD, + Address VDAddr, SourceLocation Loc); /// Returns the address of the variable marked as declare target with link /// clause OR as declare target with to clause and unified memory. - virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD); + virtual Address getAddrOfDeclareTargetVar(const VarDecl *VD); /// Emit a code for initialization of threadprivate variable. It emits /// a call to runtime library which adds initial value to the newly created diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 5baac8f0e3e2..299ee1460b3d 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -1096,8 +1096,7 @@ void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, llvm::PointerType *VarPtrTy = CGF.ConvertTypeForMem(VarTy)->getPointerTo(); llvm::Value *CastedVoidPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( VoidPtr, VarPtrTy, VD->getName() + "_on_stack"); - LValue VarAddr = - CGF.MakeNaturalAlignPointeeRawAddrLValue(CastedVoidPtr, VarTy); + LValue VarAddr = CGF.MakeNaturalAlignAddrLValue(CastedVoidPtr, VarTy); Rec.second.PrivateAddr = VarAddr.getAddress(CGF); Rec.second.GlobalizedVal = VoidPtr; @@ -1207,8 +1206,8 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, bool IsBareKernel = D.getSingleClause(); - RawAddress ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, - /*Name=*/".zero.addr"); + Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, + /*Name=*/".zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddr); llvm::SmallVector OutlinedFnArgs; // We don't emit any thread id function call in bare kernel, but because the @@ -1216,7 +1215,7 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, if (IsBareKernel) OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); else - OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).emitRawPointer(CGF)); + OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); @@ -1290,7 +1289,7 @@ void CGOpenMPRuntimeGPU::emitParallelCall(CodeGenFunction &CGF, llvm::ConstantInt::get(CGF.Int32Ty, -1), FnPtr, ID, - Bld.CreateBitOrPointerCast(CapturedVarsAddrs.emitRawPointer(CGF), + Bld.CreateBitOrPointerCast(CapturedVarsAddrs.getPointer(), CGF.VoidPtrPtrTy), llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())}; CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -1504,18 +1503,17 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, CGF.EmitBlock(PreCondBB); llvm::PHINode *PhiSrc = Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2); - PhiSrc->addIncoming(Ptr.emitRawPointer(CGF), CurrentBB); + PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB); llvm::PHINode *PhiDest = Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2); - PhiDest->addIncoming(ElemPtr.emitRawPointer(CGF), CurrentBB); + PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB); Ptr = Address(PhiSrc, Ptr.getElementType(), Ptr.getAlignment()); ElemPtr = Address(PhiDest, ElemPtr.getElementType(), ElemPtr.getAlignment()); - llvm::Value *PtrEndRaw = PtrEnd.emitRawPointer(CGF); - llvm::Value *PtrRaw = Ptr.emitRawPointer(CGF); llvm::Value *PtrDiff = Bld.CreatePtrDiff( - CGF.Int8Ty, PtrEndRaw, - Bld.CreatePointerBitCastOrAddrSpaceCast(PtrRaw, CGF.VoidPtrTy)); + CGF.Int8Ty, PtrEnd.getPointer(), + Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr.getPointer(), + CGF.VoidPtrTy)); Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)), ThenBB, ExitBB); CGF.EmitBlock(ThenBB); @@ -1530,8 +1528,8 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, TBAAAccessInfo()); Address LocalPtr = Bld.CreateConstGEP(Ptr, 1); Address LocalElemPtr = Bld.CreateConstGEP(ElemPtr, 1); - PhiSrc->addIncoming(LocalPtr.emitRawPointer(CGF), ThenBB); - PhiDest->addIncoming(LocalElemPtr.emitRawPointer(CGF), ThenBB); + PhiSrc->addIncoming(LocalPtr.getPointer(), ThenBB); + PhiDest->addIncoming(LocalElemPtr.getPointer(), ThenBB); CGF.EmitBranch(PreCondBB); CGF.EmitBlock(ExitBB); } else { @@ -1678,10 +1676,10 @@ static void emitReductionListCopy( // scope and that of functions it invokes (i.e., reduce_function). // RemoteReduceData[i] = (void*)&RemoteElem if (UpdateDestListPtr) { - CGF.EmitStoreOfScalar( - Bld.CreatePointerBitCastOrAddrSpaceCast( - DestElementAddr.emitRawPointer(CGF), CGF.VoidPtrTy), - DestElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy); + CGF.EmitStoreOfScalar(Bld.CreatePointerBitCastOrAddrSpaceCast( + DestElementAddr.getPointer(), CGF.VoidPtrTy), + DestElementPtrAddr, /*Volatile=*/false, + C.VoidPtrTy); } ++Idx; @@ -1832,7 +1830,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, // elemptr = ((CopyType*)(elemptrptr)) + I Address ElemPtr(ElemPtrPtr, CopyType, Align); if (NumIters > 1) - ElemPtr = Bld.CreateGEP(CGF, ElemPtr, Cnt); + ElemPtr = Bld.CreateGEP(ElemPtr, Cnt); // Get pointer to location in transfer medium. // MediumPtr = &medium[warp_id] @@ -1896,7 +1894,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, Loc); Address TargetElemPtr(TargetElemPtrVal, CopyType, Align); if (NumIters > 1) - TargetElemPtr = Bld.CreateGEP(CGF, TargetElemPtr, Cnt); + TargetElemPtr = Bld.CreateGEP(TargetElemPtr, Cnt); // *TargetElemPtr = SrcMediumVal; llvm::Value *SrcMediumValue = @@ -2107,9 +2105,9 @@ static llvm::Function *emitShuffleAndReduceFunction( CGF.EmitBlock(ThenBB); // reduce_function(LocalReduceList, RemoteReduceList) llvm::Value *LocalReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - LocalReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); + LocalReduceList.getPointer(), CGF.VoidPtrTy); llvm::Value *RemoteReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - RemoteReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); + RemoteReduceList.getPointer(), CGF.VoidPtrTy); CGM.getOpenMPRuntime().emitOutlinedFunctionCall( CGF, Loc, ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr}); Bld.CreateBr(MergeBB); @@ -2220,9 +2218,9 @@ static llvm::Value *emitListToGlobalCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), + GlobLVal.setAddress(Address(GlobAddr.getPointer(), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2306,7 +2304,7 @@ static llvm::Value *emitListToGlobalReduceFunction( // 1. Build a list of reduction variables. // void *RedList[] = {[0], ..., [-1]}; - RawAddress ReductionList = + Address ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); auto IPriv = Privates.begin(); llvm::Value *Idxs[] = {CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(&IdxArg), @@ -2321,10 +2319,10 @@ static llvm::Value *emitListToGlobalReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, - /*Volatile=*/false, C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, + C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2427,9 +2425,9 @@ static llvm::Value *emitGlobalToListCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), + GlobLVal.setAddress(Address(GlobAddr.getPointer(), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2528,10 +2526,10 @@ static llvm::Value *emitGlobalToListReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, - /*Volatile=*/false, C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, + C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2547,7 +2545,7 @@ static llvm::Value *emitGlobalToListReduceFunction( } // Call reduce_function(ReduceList, GlobalReduceList) - llvm::Value *GlobalReduceList = ReductionList.emitRawPointer(CGF); + llvm::Value *GlobalReduceList = ReductionList.getPointer(); Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg); llvm::Value *ReducedPtr = CGF.EmitLoadOfScalar( AddrReduceListArg, /*Volatile=*/false, C.VoidPtrTy, Loc); @@ -2878,7 +2876,7 @@ void CGOpenMPRuntimeGPU::emitReduction( } llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - ReductionList.emitRawPointer(CGF), CGF.VoidPtrTy); + ReductionList.getPointer(), CGF.VoidPtrTy); llvm::Function *ReductionFn = emitReductionFunction( CGF.CurFn->getName(), Loc, CGF.ConvertTypeForMem(ReductionArrayTy), Privates, LHSExprs, RHSExprs, ReductionOps); @@ -3108,15 +3106,15 @@ llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper( // Get the array of arguments. SmallVector Args; - Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).emitRawPointer(CGF)); - Args.emplace_back(ZeroAddr.emitRawPointer(CGF)); + Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer()); + Args.emplace_back(ZeroAddr.getPointer()); CGBuilderTy &Bld = CGF.Builder; auto CI = CS.capture_begin(); // Use global memory for data sharing. // Handle passing of global args to workers. - RawAddress GlobalArgs = + Address GlobalArgs = CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args"); llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer(); llvm::Value *DataSharingArgs[] = {GlobalArgsPtr}; @@ -3402,7 +3400,7 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas( VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType().getCanonicalType()) .getAddress(CGF); - CGF.EmitStoreOfScalar(VDAddr.emitRawPointer(CGF), VarLVal); + CGF.EmitStoreOfScalar(VDAddr.getPointer(), VarLVal); } } } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 576fe2f7a2d4..cb5a004e4f4a 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2294,7 +2294,7 @@ std::pair CodeGenFunction::EmitAsmInputLValue( Address Addr = InputValue.getAddress(*this); ConstraintStr += '*'; - return {InputValue.getPointer(*this), Addr.getElementType()}; + return {Addr.getPointer(), Addr.getElementType()}; } std::pair @@ -2701,7 +2701,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { ArgTypes.push_back(DestAddr.getType()); ArgElemTypes.push_back(DestAddr.getElementType()); - Args.push_back(DestAddr.emitRawPointer(*this)); + Args.push_back(DestAddr.getPointer()); Constraints += "=*"; Constraints += OutputConstraint; ReadOnly = ReadNone = false; @@ -3076,8 +3076,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr)); // Initialize variable-length arrays. - LValue Base = MakeNaturalAlignRawAddrLValue( - CapturedStmtInfo->getContextValue(), Ctx.getTagDeclType(RD)); + LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), + Ctx.getTagDeclType(RD)); for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType()) { auto *ExprArg = diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index e6d504bcdeca..f37ac549d10a 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -350,8 +350,7 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); llvm::Value *SrcAddrVal = EmitScalarConversion( - DstAddr.emitRawPointer(*this), - Ctx.getPointerType(Ctx.getUIntPtrType()), + DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), Ctx.getPointerType(CurField->getType()), CurCap->getLocation()); LValue SrcLV = MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); @@ -365,8 +364,7 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( CapturedVars.push_back(CV); } else { assert(CurCap->capturesVariable() && "Expected capture by reference."); - CapturedVars.push_back( - EmitLValue(*I).getAddress(*this).emitRawPointer(*this)); + CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer()); } } } @@ -377,9 +375,8 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, ASTContext &Ctx = CGF.getContext(); llvm::Value *CastedPtr = CGF.EmitScalarConversion( - AddrLV.getAddress(CGF).emitRawPointer(CGF), Ctx.getUIntPtrType(), + AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(), Ctx.getPointerType(DstType), Loc); - // FIXME: should the pointee type (DstType) be passed? Address TmpAddr = CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress(CGF); return TmpAddr; @@ -705,8 +702,8 @@ void CodeGenFunction::EmitOMPAggregateAssign( llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); SrcAddr = SrcAddr.withElementType(DestAddr.getElementType()); - llvm::Value *SrcBegin = SrcAddr.emitRawPointer(*this); - llvm::Value *DestBegin = DestAddr.emitRawPointer(*this); + llvm::Value *SrcBegin = SrcAddr.getPointer(); + llvm::Value *DestBegin = DestAddr.getPointer(); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = Builder.CreateInBoundsGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -1010,10 +1007,10 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { CopyBegin = createBasicBlock("copyin.not.master"); CopyEnd = createBasicBlock("copyin.not.master.end"); // TODO: Avoid ptrtoint conversion. - auto *MasterAddrInt = Builder.CreatePtrToInt( - MasterAddr.emitRawPointer(*this), CGM.IntPtrTy); - auto *PrivateAddrInt = Builder.CreatePtrToInt( - PrivateAddr.emitRawPointer(*this), CGM.IntPtrTy); + auto *MasterAddrInt = + Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy); + auto *PrivateAddrInt = + Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy); Builder.CreateCondBr( Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin, CopyEnd); @@ -1669,7 +1666,7 @@ Address CodeGenFunction::OMPBuilderCBHelpers::getAddrOfThreadPrivate( llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Data = - CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy); + CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy); llvm::ConstantInt *Size = CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)); std::string Suffix = getNameWithSeparators({"cache", ""}); llvm::Twine CacheName = Twine(CGM.getMangledName(VD)).concat(Suffix); @@ -2048,7 +2045,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { ->getParam(0) ->getType() .getNonReferenceType(); - RawAddress CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); + Address CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()}); llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count"); @@ -2064,7 +2061,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { LValue LCVal = EmitLValue(LoopVarRef); Address LoopVarAddress = LCVal.getAddress(*this); emitCapturedStmtCall(*this, LoopVarClosure, - {LoopVarAddress.emitRawPointer(*this), IndVar}); + {LoopVarAddress.getPointer(), IndVar}); RunCleanupsScope BodyScope(*this); EmitStmt(BodyStmt); @@ -4798,7 +4795,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.PrivateVars) { const auto *VD = cast(cast(E)->getDecl()); - RawAddress PrivatePtr = CGF.CreateMemTemp( + Address PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); CallArgs.push_back(PrivatePtr.getPointer()); @@ -4806,7 +4803,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - RawAddress PrivatePtr = + Address PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4816,7 +4813,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.LastprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - RawAddress PrivatePtr = + Address PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".lastpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4829,7 +4826,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( Ty = CGF.getContext().getPointerType(Ty); if (isAllocatableDecl(VD)) Ty = CGF.getContext().getPointerType(Ty); - RawAddress PrivatePtr = CGF.CreateMemTemp( + Address PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(Ty), ".local.ptr.addr"); auto Result = UntiedLocalVars.insert( std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid()))); @@ -4862,7 +4859,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( if (auto *DI = CGF.getDebugInfo()) if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo()) (void)DI->EmitDeclareOfAutoVariable( - Pair.first, Pair.second.getBasePointer(), CGF.Builder, + Pair.first, Pair.second.getPointer(), CGF.Builder, /*UsePointerValue*/ true); } // Adjust mapping for internal locals by mapping actual memory instead of @@ -4915,14 +4912,14 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = Address( - CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), - CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = + Address(CGF.EmitScalarConversion( + Replacement.getPointer(), CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -4973,7 +4970,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, + Replacement.getPointer(), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5092,7 +5089,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( // If there is no user-defined mapper, the mapper array will be nullptr. In // this case, we don't need to privatize it. if (!isa_and_nonnull( - InputInfo.MappersArray.emitRawPointer(*this))) { + InputInfo.MappersArray.getPointer())) { MVD = createImplicitFirstprivateForType( getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc()); TargetScope.addPrivate(MVD, InputInfo.MappersArray); @@ -5118,7 +5115,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - RawAddress PrivatePtr = + Address PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -5197,14 +5194,14 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = Address( - CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), - CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = + Address(CGF.EmitScalarConversion( + Replacement.getPointer(), CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -5250,7 +5247,7 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, + Replacement.getPointer(), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5397,7 +5394,7 @@ void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) { Dependencies.DepExprs.append(DC->varlist_begin(), DC->varlist_end()); Address DepAddr = CGM.getOpenMPRuntime().emitDepobjDependClause( *this, Dependencies, DC->getBeginLoc()); - EmitStoreOfScalar(DepAddr.emitRawPointer(*this), DOLVal); + EmitStoreOfScalar(DepAddr.getPointer(), DOLVal); return; } if (const auto *DC = S.getSingleClause()) { @@ -6474,21 +6471,21 @@ static void emitOMPAtomicCompareExpr( D->getType()->hasSignedIntegerRepresentation()); llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{ - XAddr.emitRawPointer(CGF), XAddr.getElementType(), + XAddr.getPointer(), XAddr.getElementType(), X->getType()->hasSignedIntegerRepresentation(), X->getType().isVolatileQualified()}; llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal; if (V) { LValue LV = CGF.EmitLValue(V); Address Addr = LV.getAddress(CGF); - VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), + VOpVal = {Addr.getPointer(), Addr.getElementType(), V->getType()->hasSignedIntegerRepresentation(), V->getType().isVolatileQualified()}; } if (R) { LValue LV = CGF.EmitLValue(R); Address Addr = LV.getAddress(CGF); - ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), + ROpVal = {Addr.getPointer(), Addr.getElementType(), R->getType()->hasSignedIntegerRepresentation(), R->getType().isVolatileQualified()}; } @@ -7032,7 +7029,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) { std::tie(NumDependences, DependenciesArray) = CGM.getOpenMPRuntime().emitDependClause(*this, Data.Dependences, S.getBeginLoc()); - DependenceList = DependenciesArray.emitRawPointer(*this); + DependenceList = DependenciesArray.getPointer(); } Data.HasNowaitClause = S.hasClausesOfKind(); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 862369ae009f..8dee3f74b44b 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -201,13 +201,14 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, // Find the first store of "this", which will be to the alloca associated // with "this". - Address ThisPtr = makeNaturalAddressForPointer( - &*AI, MD->getFunctionObjectParameterType(), - CGM.getClassPointerAlignment(MD->getParent())); + Address ThisPtr = + Address(&*AI, ConvertTypeForMem(MD->getFunctionObjectParameterType()), + CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = llvm::find_if(*EntryBB, [&](llvm::Instruction &I) { - return isa(I) && I.getOperand(0) == &*AI; + return isa(I) && + I.getOperand(0) == ThisPtr.getPointer(); }); assert(ThisStore != EntryBB->end() && "Store of this should be in entry block?"); diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index cc9ad10ae596..1e6f67250583 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -14,13 +14,12 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H -#include "Address.h" -#include "CodeGenTBAA.h" -#include "EHScopeStack.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" -#include "llvm/IR/Type.h" #include "llvm/IR/Value.h" +#include "llvm/IR/Type.h" +#include "Address.h" +#include "CodeGenTBAA.h" namespace llvm { class Constant; @@ -29,64 +28,57 @@ namespace llvm { namespace clang { namespace CodeGen { -class AggValueSlot; -class CGBuilderTy; -class CodeGenFunction; -struct CGBitFieldInfo; + class AggValueSlot; + class CodeGenFunction; + struct CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an /// expression that is evaluated. It can be one of three things: either a /// simple LLVM SSA value, a pair of SSA values for complex numbers, or the /// address of an aggregate value in memory. class RValue { - friend struct DominatingValue; + enum Flavor { Scalar, Complex, Aggregate }; - enum FlavorEnum { Scalar, Complex, Aggregate }; + // The shift to make to an aggregate's alignment to make it look + // like a pointer. + enum { AggAlignShift = 4 }; - union { - // Stores first and second value. - struct { - llvm::Value *first; - llvm::Value *second; - } Vals; - - // Stores aggregate address. - Address AggregateAddr; - }; - - unsigned IsVolatile : 1; - unsigned Flavor : 2; + // Stores first value and flavor. + llvm::PointerIntPair V1; + // Stores second value and volatility. + llvm::PointerIntPair V2; + // Stores element type for aggregate values. + llvm::Type *ElementType; public: - RValue() : Vals{nullptr, nullptr}, Flavor(Scalar) {} - - bool isScalar() const { return Flavor == Scalar; } - bool isComplex() const { return Flavor == Complex; } - bool isAggregate() const { return Flavor == Aggregate; } + bool isScalar() const { return V1.getInt() == Scalar; } + bool isComplex() const { return V1.getInt() == Complex; } + bool isAggregate() const { return V1.getInt() == Aggregate; } - bool isVolatileQualified() const { return IsVolatile; } + bool isVolatileQualified() const { return V2.getInt(); } /// getScalarVal() - Return the Value* of this scalar value. llvm::Value *getScalarVal() const { assert(isScalar() && "Not a scalar!"); - return Vals.first; + return V1.getPointer(); } /// getComplexVal - Return the real/imag components of this complex value. /// std::pair getComplexVal() const { - return std::make_pair(Vals.first, Vals.second); + return std::make_pair(V1.getPointer(), V2.getPointer()); } /// getAggregateAddr() - Return the Value* of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); - return AggregateAddr; + auto align = reinterpret_cast(V2.getPointer()) >> AggAlignShift; + return Address( + V1.getPointer(), ElementType, CharUnits::fromQuantity(align)); } - - llvm::Value *getAggregatePointer(QualType PointeeType, - CodeGenFunction &CGF) const { - return getAggregateAddress().getBasePointer(); + llvm::Value *getAggregatePointer() const { + assert(isAggregate() && "Not an aggregate!"); + return V1.getPointer(); } static RValue getIgnored() { @@ -96,19 +88,17 @@ public: static RValue get(llvm::Value *V) { RValue ER; - ER.Vals.first = V; - ER.Flavor = Scalar; - ER.IsVolatile = false; + ER.V1.setPointer(V); + ER.V1.setInt(Scalar); + ER.V2.setInt(false); return ER; } - static RValue get(Address Addr, CodeGenFunction &CGF) { - return RValue::get(Addr.emitRawPointer(CGF)); - } static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { RValue ER; - ER.Vals = {V1, V2}; - ER.Flavor = Complex; - ER.IsVolatile = false; + ER.V1.setPointer(V1); + ER.V2.setPointer(V2); + ER.V1.setInt(Complex); + ER.V2.setInt(false); return ER; } static RValue getComplex(const std::pair &C) { @@ -117,15 +107,15 @@ public: // FIXME: Aggregate rvalues need to retain information about whether they are // volatile or not. Remove default to find all places that probably get this // wrong. - - /// Convert an Address to an RValue. If the Address is not - /// signed, create an RValue using the unsigned address. Otherwise, resign the - /// address using the provided type. static RValue getAggregate(Address addr, bool isVolatile = false) { RValue ER; - ER.AggregateAddr = addr; - ER.Flavor = Aggregate; - ER.IsVolatile = isVolatile; + ER.V1.setPointer(addr.getPointer()); + ER.V1.setInt(Aggregate); + ER.ElementType = addr.getElementType(); + + auto align = static_cast(addr.getAlignment().getQuantity()); + ER.V2.setPointer(reinterpret_cast(align << AggAlignShift)); + ER.V2.setInt(isVolatile); return ER; } }; @@ -188,10 +178,8 @@ class LValue { MatrixElt // This is a matrix element, use getVector* } LVType; - union { - Address Addr = Address::invalid(); - llvm::Value *V; - }; + llvm::Value *V; + llvm::Type *ElementType; union { // Index into a vector subscript: V[i] @@ -209,6 +197,10 @@ class LValue { // 'const' is unused here Qualifiers Quals; + // The alignment to use when accessing this lvalue. (For vector elements, + // this is the alignment of the whole vector.) + unsigned Alignment; + // objective-c's ivar bool Ivar:1; @@ -242,19 +234,23 @@ class LValue { Expr *BaseIvarExp; private: - void Initialize(QualType Type, Qualifiers Quals, Address Addr, + void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { + assert((!Alignment.isZero() || Type->isIncompleteType()) && + "initializing l-value with zero alignment!"); + if (isGlobalReg()) + assert(ElementType == nullptr && "Global reg does not store elem type"); + else + assert(ElementType != nullptr && "Must have elem type"); + this->Type = Type; this->Quals = Quals; const unsigned MaxAlign = 1U << 31; - CharUnits Alignment = Addr.getAlignment(); - assert((isGlobalReg() || !Alignment.isZero() || Type->isIncompleteType()) && - "initializing l-value with zero alignment!"); - if (Alignment.getQuantity() > MaxAlign) { - assert(false && "Alignment exceeds allowed max!"); - Alignment = CharUnits::fromQuantity(MaxAlign); - } - this->Addr = Addr; + this->Alignment = Alignment.getQuantity() <= MaxAlign + ? Alignment.getQuantity() + : MaxAlign; + assert(this->Alignment == Alignment.getQuantity() && + "Alignment exceeds allowed max!"); this->BaseInfo = BaseInfo; this->TBAAInfo = TBAAInfo; @@ -263,20 +259,9 @@ private: this->ImpreciseLifetime = false; this->Nontemporal = false; this->ThreadLocalRef = false; - this->IsKnownNonNull = false; this->BaseIvarExp = nullptr; } - void initializeSimpleLValue(Address Addr, QualType Type, - LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, - ASTContext &Context) { - Qualifiers QS = Type.getQualifiers(); - QS.setObjCGCAttr(Context.getObjCGCAttrKind(Type)); - LVType = Simple; - Initialize(Type, QS, Addr, BaseInfo, TBAAInfo); - assert(Addr.getBasePointer()->getType()->isPointerTy()); - } - public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } @@ -343,8 +328,8 @@ public: LangAS getAddressSpace() const { return Quals.getAddressSpace(); } - CharUnits getAlignment() const { return Addr.getAlignment(); } - void setAlignment(CharUnits A) { Addr.setAlignment(A); } + CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } + void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } LValueBaseInfo getBaseInfo() const { return BaseInfo; } void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } @@ -360,32 +345,28 @@ public: // simple lvalue llvm::Value *getPointer(CodeGenFunction &CGF) const { assert(isSimple()); - return Addr.getBasePointer(); + return V; } - llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - assert(isSimple()); - return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; - } - Address getAddress(CodeGenFunction &CGF) const { - // FIXME: remove parameter. - return Addr; + return Address(getPointer(CGF), ElementType, getAlignment(), + isKnownNonNull()); + } + void setAddress(Address address) { + assert(isSimple()); + V = address.getPointer(); + ElementType = address.getElementType(); + Alignment = address.getAlignment().getQuantity(); + IsKnownNonNull = address.isKnownNonNull(); } - - void setAddress(Address address) { Addr = address; } // vector elt lvalue Address getVectorAddress() const { - assert(isVectorElt()); - return Addr; - } - llvm::Value *getRawVectorPointer(CodeGenFunction &CGF) const { - assert(isVectorElt()); - return Addr.emitRawPointer(CGF); + return Address(getVectorPointer(), ElementType, getAlignment(), + (KnownNonNull_t)isKnownNonNull()); } llvm::Value *getVectorPointer() const { assert(isVectorElt()); - return Addr.getBasePointer(); + return V; } llvm::Value *getVectorIdx() const { assert(isVectorElt()); @@ -393,12 +374,12 @@ public: } Address getMatrixAddress() const { - assert(isMatrixElt()); - return Addr; + return Address(getMatrixPointer(), ElementType, getAlignment(), + (KnownNonNull_t)isKnownNonNull()); } llvm::Value *getMatrixPointer() const { assert(isMatrixElt()); - return Addr.getBasePointer(); + return V; } llvm::Value *getMatrixIdx() const { assert(isMatrixElt()); @@ -407,12 +388,12 @@ public: // extended vector elements. Address getExtVectorAddress() const { - assert(isExtVectorElt()); - return Addr; + return Address(getExtVectorPointer(), ElementType, getAlignment(), + (KnownNonNull_t)isKnownNonNull()); } - llvm::Value *getRawExtVectorPointer(CodeGenFunction &CGF) const { + llvm::Value *getExtVectorPointer() const { assert(isExtVectorElt()); - return Addr.emitRawPointer(CGF); + return V; } llvm::Constant *getExtVectorElts() const { assert(isExtVectorElt()); @@ -421,14 +402,10 @@ public: // bitfield lvalue Address getBitFieldAddress() const { - assert(isBitField()); - return Addr; - } - llvm::Value *getRawBitFieldPointer(CodeGenFunction &CGF) const { - assert(isBitField()); - return Addr.emitRawPointer(CGF); + return Address(getBitFieldPointer(), ElementType, getAlignment(), + (KnownNonNull_t)isKnownNonNull()); } - + llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; } const CGBitFieldInfo &getBitFieldInfo() const { assert(isBitField()); return *BitFieldInfo; @@ -437,13 +414,18 @@ public: // global register lvalue llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } - static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, + static LValue MakeAddr(Address address, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { + Qualifiers qs = type.getQualifiers(); + qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); + LValue R; R.LVType = Simple; - R.initializeSimpleLValue(Addr, type, BaseInfo, TBAAInfo, Context); - R.Addr = Addr; - assert(Addr.getType()->isPointerTy()); + assert(address.getPointer()->getType()->isPointerTy()); + R.V = address.getPointer(); + R.ElementType = address.getElementType(); + R.IsKnownNonNull = address.isKnownNonNull(); + R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); return R; } @@ -452,18 +434,26 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = VectorElt; + R.V = vecAddress.getPointer(); + R.ElementType = vecAddress.getElementType(); R.VectorIdx = Idx; - R.Initialize(type, type.getQualifiers(), vecAddress, BaseInfo, TBAAInfo); + R.IsKnownNonNull = vecAddress.isKnownNonNull(); + R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), + BaseInfo, TBAAInfo); return R; } - static LValue MakeExtVectorElt(Address Addr, llvm::Constant *Elts, + static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = ExtVectorElt; + R.V = vecAddress.getPointer(); + R.ElementType = vecAddress.getElementType(); R.VectorElts = Elts; - R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); + R.IsKnownNonNull = vecAddress.isKnownNonNull(); + R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), + BaseInfo, TBAAInfo); return R; } @@ -478,8 +468,12 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = BitField; + R.V = Addr.getPointer(); + R.ElementType = Addr.getElementType(); R.BitFieldInfo = &Info; - R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); + R.IsKnownNonNull = Addr.isKnownNonNull(); + R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, + TBAAInfo); return R; } @@ -487,9 +481,11 @@ public: QualType type) { LValue R; R.LVType = GlobalReg; - R.Initialize(type, type.getQualifiers(), Address::invalid(), - LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); R.V = V; + R.ElementType = nullptr; + R.IsKnownNonNull = true; + R.Initialize(type, type.getQualifiers(), alignment, + LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); return R; } @@ -498,8 +494,12 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = MatrixElt; + R.V = matAddress.getPointer(); + R.ElementType = matAddress.getElementType(); R.VectorIdx = Idx; - R.Initialize(type, type.getQualifiers(), matAddress, BaseInfo, TBAAInfo); + R.IsKnownNonNull = matAddress.isKnownNonNull(); + R.Initialize(type, type.getQualifiers(), matAddress.getAlignment(), + BaseInfo, TBAAInfo); return R; } @@ -643,17 +643,17 @@ public: return NeedsGCBarriers_t(ObjCGCFlag); } - llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; - - llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; + llvm::Value *getPointer() const { + return Addr.getPointer(); } Address getAddress() const { return Addr; } - bool isIgnored() const { return !Addr.isValid(); } + bool isIgnored() const { + return !Addr.isValid(); + } CharUnits getAlignment() const { return Addr.getAlignment(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 44103884940f..f2ebaf767452 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -193,35 +193,26 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() { CGF.Builder.setDefaultConstrainedRounding(OldRounding); } -static LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, - bool ForPointeeType, - CodeGenFunction &CGF) { +LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - CharUnits Alignment = - CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType); - Address Addr = Address(V, CGF.ConvertTypeForMem(T), Alignment); - return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); -} - -LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); + CharUnits Alignment = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo); + Address Addr(V, ConvertTypeForMem(T), Alignment); + return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo); } +/// Given a value of type T* that may not be to a complete object, +/// construct an l-value with the natural pointee alignment of T. LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); -} - -LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V, - QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); + LValueBaseInfo BaseInfo; + TBAAAccessInfo TBAAInfo; + CharUnits Align = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, + /* forPointeeType= */ true); + Address Addr(V, ConvertTypeForMem(T), Align); + return MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); } -LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, - QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); -} llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { return CGM.getTypes().ConvertTypeForMem(T); @@ -534,8 +525,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { ReturnBlock.getBlock()->eraseFromParent(); } if (ReturnValue.isValid()) { - auto *RetAlloca = - dyn_cast(ReturnValue.emitRawPointer(*this)); + auto *RetAlloca = dyn_cast(ReturnValue.getPointer()); if (RetAlloca && RetAlloca->use_empty()) { RetAlloca->eraseFromParent(); ReturnValue = Address::invalid(); @@ -1132,14 +1122,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, auto AI = CurFn->arg_begin(); if (CurFnInfo->getReturnInfo().isSRetAfterThis()) ++AI; - ReturnValue = makeNaturalAddressForPointer( - &*AI, RetTy, CurFnInfo->getReturnInfo().getIndirectAlign(), false, - nullptr, nullptr, KnownNonNull); + ReturnValue = + Address(&*AI, ConvertType(RetTy), + CurFnInfo->getReturnInfo().getIndirectAlign(), KnownNonNull); if (!CurFnInfo->getReturnInfo().getIndirectByVal()) { - ReturnValuePointer = - CreateDefaultAlignTempAlloca(ReturnValue.getType(), "result.ptr"); - Builder.CreateStore(ReturnValue.emitRawPointer(*this), - ReturnValuePointer); + ReturnValuePointer = CreateDefaultAlignTempAlloca( + ReturnValue.getPointer()->getType(), "result.ptr"); + Builder.CreateStore(ReturnValue.getPointer(), ReturnValuePointer); } } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { @@ -1200,9 +1189,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // or contains the address of the enclosing object). LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - // If the enclosing object was captured by value, just use its - // address. Sign this pointer. - CXXThisValue = ThisFieldLValue.getPointer(*this); + // If the enclosing object was captured by value, just use its address. + CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); } else { // Load the lvalue pointed to by the field, since '*this' was captured // by reference. @@ -2024,9 +2012,8 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); Address begin = dest.withElementType(CGF.Int8Ty); - llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(), - begin.emitRawPointer(CGF), - sizeInChars, "vla.end"); + llvm::Value *end = Builder.CreateInBoundsGEP( + begin.getElementType(), begin.getPointer(), sizeInChars, "vla.end"); llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock(); llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop"); @@ -2037,7 +2024,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, CGF.EmitBlock(loopBB); llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur"); - cur->addIncoming(begin.emitRawPointer(CGF), originBB); + cur->addIncoming(begin.getPointer(), originBB); CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize); @@ -2230,10 +2217,10 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, addr = addr.withElementType(baseType); } else { // Create the actual GEP. - addr = Address(Builder.CreateInBoundsGEP(addr.getElementType(), - addr.emitRawPointer(*this), - gepIndices, "array.begin"), - ConvertTypeForMem(eltType), addr.getAlignment()); + addr = Address(Builder.CreateInBoundsGEP( + addr.getElementType(), addr.getPointer(), gepIndices, "array.begin"), + ConvertTypeForMem(eltType), + addr.getAlignment()); } baseType = eltType; @@ -2574,7 +2561,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) { Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, Address Addr) { assert(D->hasAttr() && "no annotate attribute"); - llvm::Value *V = Addr.emitRawPointer(*this); + llvm::Value *V = Addr.getPointer(); llvm::Type *VTy = V->getType(); auto *PTy = dyn_cast(VTy); unsigned AS = PTy ? PTy->getAddressSpace() : 0; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8dd6da5f85f1..e8f8aa601ed0 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -151,9 +151,6 @@ struct DominatingLLVMValue { /// Answer whether the given value needs extra work to be saved. static bool needsSaving(llvm::Value *value) { - if (!value) - return false; - // If it's not an instruction, we don't need to save. if (!isa(value)) return false; @@ -180,28 +177,21 @@ template <> struct DominatingValue
{ typedef Address type; struct saved_type { - DominatingLLVMValue::saved_type BasePtr; + DominatingLLVMValue::saved_type SavedValue; llvm::Type *ElementType; CharUnits Alignment; - DominatingLLVMValue::saved_type Offset; - llvm::PointerType *EffectiveType; }; static bool needsSaving(type value) { - if (DominatingLLVMValue::needsSaving(value.getBasePointer()) || - DominatingLLVMValue::needsSaving(value.getOffset())) - return true; - return false; + return DominatingLLVMValue::needsSaving(value.getPointer()); } static saved_type save(CodeGenFunction &CGF, type value) { - return {DominatingLLVMValue::save(CGF, value.getBasePointer()), - value.getElementType(), value.getAlignment(), - DominatingLLVMValue::save(CGF, value.getOffset()), value.getType()}; + return { DominatingLLVMValue::save(CGF, value.getPointer()), + value.getElementType(), value.getAlignment() }; } static type restore(CodeGenFunction &CGF, saved_type value) { - return Address(DominatingLLVMValue::restore(CGF, value.BasePtr), - value.ElementType, value.Alignment, - DominatingLLVMValue::restore(CGF, value.Offset)); + return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), + value.ElementType, value.Alignment); } }; @@ -211,26 +201,14 @@ template <> struct DominatingValue { class saved_type { enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, AggregateAddress, ComplexAddress }; - union { - struct { - DominatingLLVMValue::saved_type first, second; - } Vals; - DominatingValue
::saved_type AggregateAddr; - }; + + llvm::Value *Value; + llvm::Type *ElementType; LLVM_PREFERRED_TYPE(Kind) unsigned K : 3; - unsigned IsVolatile : 1; - - saved_type(DominatingLLVMValue::saved_type Val1, unsigned K) - : Vals{Val1, DominatingLLVMValue::saved_type()}, K(K) {} - - saved_type(DominatingLLVMValue::saved_type Val1, - DominatingLLVMValue::saved_type Val2) - : Vals{Val1, Val2}, K(ComplexAddress) {} - - saved_type(DominatingValue
::saved_type AggregateAddr, - bool IsVolatile, unsigned K) - : AggregateAddr(AggregateAddr), K(K) {} + unsigned Align : 29; + saved_type(llvm::Value *v, llvm::Type *e, Kind k, unsigned a = 0) + : Value(v), ElementType(e), K(k), Align(a) {} public: static bool needsSaving(RValue value); @@ -681,7 +659,7 @@ public: llvm::Value *Size; public: - CallLifetimeEnd(RawAddress addr, llvm::Value *size) + CallLifetimeEnd(Address addr, llvm::Value *size) : Addr(addr.getPointer()), Size(size) {} void Emit(CodeGenFunction &CGF, Flags flags) override { @@ -706,7 +684,7 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - RawAddress NormalCleanupDest = RawAddress::invalid(); + Address NormalCleanupDest = Address::invalid(); unsigned NextCleanupDestIndex = 1; @@ -841,10 +819,10 @@ public: template void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) { if (!isInConditionalBranch()) - return pushCleanupAfterFullExprWithActiveFlag( - Kind, RawAddress::invalid(), A...); + return pushCleanupAfterFullExprWithActiveFlag(Kind, Address::invalid(), + A...); - RawAddress ActiveFlag = createCleanupActiveFlag(); + Address ActiveFlag = createCleanupActiveFlag(); assert(!DominatingValue
::needsSaving(ActiveFlag) && "cleanup active flag should never need saving"); @@ -857,7 +835,7 @@ public: template void pushCleanupAfterFullExprWithActiveFlag(CleanupKind Kind, - RawAddress ActiveFlag, As... A) { + Address ActiveFlag, As... A) { LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind, ActiveFlag.isValid()}; @@ -872,7 +850,7 @@ public: new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer + sizeof(Header)) T(A...); if (Header.IsConditional) - new (Buffer + sizeof(Header) + sizeof(T)) RawAddress(ActiveFlag); + new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag); } /// Set up the last cleanup that was pushed as a conditional @@ -881,8 +859,8 @@ public: initFullExprCleanupWithFlag(createCleanupActiveFlag()); } - void initFullExprCleanupWithFlag(RawAddress ActiveFlag); - RawAddress createCleanupActiveFlag(); + void initFullExprCleanupWithFlag(Address ActiveFlag); + Address createCleanupActiveFlag(); /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the @@ -1070,7 +1048,7 @@ public: QualType VarTy = LocalVD->getType(); if (VarTy->isReferenceType()) { Address Temp = CGF.CreateMemTemp(VarTy); - CGF.Builder.CreateStore(TempAddr.emitRawPointer(CGF), Temp); + CGF.Builder.CreateStore(TempAddr.getPointer(), Temp); TempAddr = Temp; } SavedTempAddresses.try_emplace(LocalVD, TempAddr); @@ -1265,12 +1243,10 @@ public: /// one branch or the other of a conditional expression. bool isInConditionalBranch() const { return OutermostConditional != nullptr; } - void setBeforeOutermostConditional(llvm::Value *value, Address addr, - CodeGenFunction &CGF) { + void setBeforeOutermostConditional(llvm::Value *value, Address addr) { assert(isInConditionalBranch()); llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - auto store = - new llvm::StoreInst(value, addr.emitRawPointer(CGF), &block->back()); + auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back()); store->setAlignment(addr.getAlignment().getAsAlign()); } @@ -1625,7 +1601,7 @@ public: /// If \p StepV is null, the default increment is 1. void maybeUpdateMCDCTestVectorBitmap(const Expr *E) { if (isMCDCCoverageEnabled() && isBinaryLogicalOp(E)) { - PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr, *this); + PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr); PGO.setCurrentStmt(E); } } @@ -1633,7 +1609,7 @@ public: /// Update the MCDC temp value with the condition's evaluated result. void maybeUpdateMCDCCondBitmap(const Expr *E, llvm::Value *Val) { if (isMCDCCoverageEnabled()) { - PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val, *this); + PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val); PGO.setCurrentStmt(E); } } @@ -1728,7 +1704,7 @@ public: : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue), OldCXXThisAlignment(CGF.CXXThisAlignment), SourceLocScope(E, CGF.CurSourceLocExprScope) { - CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getBasePointer(); + CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer(); CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment(); } ~CXXDefaultInitExprScope() { @@ -2114,7 +2090,7 @@ public: llvm::Value *getExceptionFromSlot(); llvm::Value *getSelectorFromSlot(); - RawAddress getNormalCleanupDestSlot(); + Address getNormalCleanupDestSlot(); llvm::BasicBlock *getUnreachableBlock() { if (!UnreachableBlock) { @@ -2603,40 +2579,10 @@ public: // Helpers //===--------------------------------------------------------------------===// - Address mergeAddressesInConditionalExpr(Address LHS, Address RHS, - llvm::BasicBlock *LHSBlock, - llvm::BasicBlock *RHSBlock, - llvm::BasicBlock *MergeBlock, - QualType MergedType) { - Builder.SetInsertPoint(MergeBlock); - llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); - PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); - PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); - LHS.replaceBasePointer(PtrPhi); - LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); - return LHS; - } - - /// Construct an address with the natural alignment of T. If a pointer to T - /// is expected to be signed, the pointer passed to this function must have - /// been signed, and the returned Address will have the pointer authentication - /// information needed to authenticate the signed pointer. - Address makeNaturalAddressForPointer( - llvm::Value *Ptr, QualType T, CharUnits Alignment = CharUnits::Zero(), - bool ForPointeeType = false, LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr, - KnownNonNull_t IsKnownNonNull = NotKnownNonNull) { - if (Alignment.isZero()) - Alignment = - CGM.getNaturalTypeAlignment(T, BaseInfo, TBAAInfo, ForPointeeType); - return Address(Ptr, ConvertTypeForMem(T), Alignment, nullptr, - IsKnownNonNull); - } - LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source = AlignmentSource::Type) { - return MakeAddrLValue(Addr, T, LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(T)); + return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), + CGM.getTBAAAccessInfo(T)); } LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo, @@ -2646,14 +2592,6 @@ public: LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source = AlignmentSource::Type) { - return MakeAddrLValue(makeNaturalAddressForPointer(V, T, Alignment), T, - LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); - } - - /// Same as MakeAddrLValue above except that the pointer is known to be - /// unsigned. - LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, - AlignmentSource Source = AlignmentSource::Type) { Address Addr(V, ConvertTypeForMem(T), Alignment); return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); @@ -2666,18 +2604,9 @@ public: TBAAAccessInfo()); } - /// Given a value of type T* that may not be to a complete object, construct - /// an l-value with the natural pointee alignment of T. LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); - LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); - /// Same as MakeNaturalAlignPointeeAddrLValue except that the pointer is known - /// to be unsigned. - LValue MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T); - - LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T); - Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo = nullptr, TBAAAccessInfo *PointeeTBAAInfo = nullptr); @@ -2726,13 +2655,13 @@ public: /// more efficient if the caller knows that the address will not be exposed. llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr); - RawAddress CreateTempAlloca(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr, - RawAddress *Alloca = nullptr); - RawAddress CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); + Address CreateTempAlloca(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr, + Address *Alloca = nullptr); + Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr); /// CreateDefaultAlignedTempAlloca - This creates an alloca with the /// default ABI alignment of the given LLVM type. @@ -2744,8 +2673,8 @@ public: /// not hand this address off to arbitrary IRGen routines, and especially /// do not pass it as an argument to a function that might expect a /// properly ABI-aligned value. - RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name = "tmp"); + Address CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name = "tmp"); /// CreateIRTemp - Create a temporary IR object of the given type, with /// appropriate alignment. This routine should only be used when an temporary @@ -2755,31 +2684,32 @@ public: /// /// That is, this is exactly equivalent to CreateMemTemp, but calling /// ConvertType instead of ConvertTypeForMem. - RawAddress CreateIRTemp(QualType T, const Twine &Name = "tmp"); + Address CreateIRTemp(QualType T, const Twine &Name = "tmp"); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen and cast it to the default address space. Returns /// the original alloca instruction by \p Alloca if it is not nullptr. - RawAddress CreateMemTemp(QualType T, const Twine &Name = "tmp", - RawAddress *Alloca = nullptr); - RawAddress CreateMemTemp(QualType T, CharUnits Align, - const Twine &Name = "tmp", - RawAddress *Alloca = nullptr); + Address CreateMemTemp(QualType T, const Twine &Name = "tmp", + Address *Alloca = nullptr); + Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp", + Address *Alloca = nullptr); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen without casting it to the default address space. - RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); - RawAddress CreateMemTempWithoutCast(QualType T, CharUnits Align, - const Twine &Name = "tmp"); + Address CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); + Address CreateMemTempWithoutCast(QualType T, CharUnits Align, + const Twine &Name = "tmp"); /// CreateAggTemp - Create a temporary memory object for the given /// aggregate type. AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp", - RawAddress *Alloca = nullptr) { - return AggValueSlot::forAddr( - CreateMemTemp(T, Name, Alloca), T.getQualifiers(), - AggValueSlot::IsNotDestructed, AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap); + Address *Alloca = nullptr) { + return AggValueSlot::forAddr(CreateMemTemp(T, Name, Alloca), + T.getQualifiers(), + AggValueSlot::IsNotDestructed, + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, + AggValueSlot::DoesNotOverlap); } /// EvaluateExprAsBool - Perform the usual unary conversions on the specified @@ -3153,25 +3083,6 @@ public: /// calls to EmitTypeCheck can be skipped. bool sanitizePerformTypeCheck() const; - void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, - QualType Type, SanitizerSet SkippedChecks = SanitizerSet(), - llvm::Value *ArraySize = nullptr) { - if (!sanitizePerformTypeCheck()) - return; - EmitTypeCheck(TCK, Loc, LV.emitRawPointer(*this), Type, LV.getAlignment(), - SkippedChecks, ArraySize); - } - - void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, Address Addr, - QualType Type, CharUnits Alignment = CharUnits::Zero(), - SanitizerSet SkippedChecks = SanitizerSet(), - llvm::Value *ArraySize = nullptr) { - if (!sanitizePerformTypeCheck()) - return; - EmitTypeCheck(TCK, Loc, Addr.emitRawPointer(*this), Type, Alignment, - SkippedChecks, ArraySize); - } - /// Emit a check that \p V is the address of storage of the /// appropriate size and alignment for an object of type \p Type /// (or if ArraySize is provided, for an array of that bound). @@ -3272,17 +3183,17 @@ public: /// Address with original alloca instruction. Invalid if the variable was /// emitted as a global constant. - RawAddress AllocaAddr; + Address AllocaAddr; struct Invalid {}; AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()), - AllocaAddr(RawAddress::invalid()) {} + AllocaAddr(Address::invalid()) {} AutoVarEmission(const VarDecl &variable) : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr), IsEscapingByRef(false), IsConstantAggregate(false), - SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {} + SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {} bool wasEmittedAsGlobal() const { return !Addr.isValid(); } @@ -3305,7 +3216,7 @@ public: } /// Returns the address for the original alloca instruction. - RawAddress getOriginalAllocatedAddress() const { return AllocaAddr; } + Address getOriginalAllocatedAddress() const { return AllocaAddr; } /// Returns the address of the object within this declaration. /// Note that this does not chase the forwarding pointer for @@ -3335,32 +3246,23 @@ public: llvm::GlobalValue::LinkageTypes Linkage); class ParamValue { - union { - Address Addr; - llvm::Value *Value; - }; - - bool IsIndirect; - - ParamValue(llvm::Value *V) : Value(V), IsIndirect(false) {} - ParamValue(Address A) : Addr(A), IsIndirect(true) {} - + llvm::Value *Value; + llvm::Type *ElementType; + unsigned Alignment; + ParamValue(llvm::Value *V, llvm::Type *T, unsigned A) + : Value(V), ElementType(T), Alignment(A) {} public: static ParamValue forDirect(llvm::Value *value) { - return ParamValue(value); + return ParamValue(value, nullptr, 0); } static ParamValue forIndirect(Address addr) { assert(!addr.getAlignment().isZero()); - return ParamValue(addr); + return ParamValue(addr.getPointer(), addr.getElementType(), + addr.getAlignment().getQuantity()); } - bool isIndirect() const { return IsIndirect; } - llvm::Value *getAnyValue() const { - if (!isIndirect()) - return Value; - assert(!Addr.hasOffset() && "unexpected offset"); - return Addr.getBasePointer(); - } + bool isIndirect() const { return Alignment != 0; } + llvm::Value *getAnyValue() const { return Value; } llvm::Value *getDirectValue() const { assert(!isIndirect()); @@ -3369,7 +3271,8 @@ public: Address getIndirectAddress() const { assert(isIndirect()); - return Addr; + return Address(Value, ElementType, CharUnits::fromQuantity(Alignment), + KnownNonNull); } }; @@ -4279,9 +4182,6 @@ public: const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name = ""); - llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, - ArrayRef
args, - const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, const Twine &name = ""); @@ -4308,12 +4208,6 @@ public: CXXDtorType Type, const CXXRecordDecl *RD); - llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { - return Addr.getBasePointer(); - } - - bool isPointerKnownNonNull(const Expr *E); - // Return the copy constructor name with the prefix "__copy_constructor_" // removed. static std::string getNonTrivialCopyConstructorStr(QualType QT, @@ -4886,11 +4780,6 @@ public: SourceLocation Loc, const Twine &Name = ""); - Address EmitCheckedInBoundsGEP(Address Addr, ArrayRef IdxList, - llvm::Type *elementType, bool SignedIndices, - bool IsSubtraction, SourceLocation Loc, - CharUnits Align, const Twine &Name = ""); - /// Specifies which type of sanitizer check to apply when handling a /// particular builtin. enum BuiltinCheckKind { @@ -4953,10 +4842,6 @@ public: void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, AbstractCallee AC, unsigned ParmNum); - void EmitNonNullArgCheck(Address Addr, QualType ArgType, - SourceLocation ArgLoc, AbstractCallee AC, - unsigned ParmNum); - /// EmitCallArg - Emit a single call argument. void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); @@ -5165,7 +5050,7 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); CGF.Builder.CreateStore(value, alloca); - return saved_type(alloca.emitRawPointer(CGF), true); + return saved_type(alloca.getPointer(), true); } inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 00b3bfcaa0bc..e3ed5e90f2d3 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -7267,7 +7267,7 @@ void CodeGenFunction::EmitDeclMetadata() { for (auto &I : LocalDeclMap) { const Decl *D = I.first; - llvm::Value *Addr = I.second.emitRawPointer(*this); + llvm::Value *Addr = I.second.getPointer(); if (auto *Alloca = dyn_cast(Addr)) { llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); Alloca->setMetadata( diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 76704c4d7be4..2619edfeb7dc 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1239,8 +1239,7 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) { void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, - CodeGenFunction &CGF) { + Address MCDCCondBitmapAddr) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1263,7 +1262,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, Builder.getInt64(FunctionHash), Builder.getInt32(RegionMCDCState->BitmapBytes), Builder.getInt32(MCDCTestVectorBitmapOffset), - MCDCCondBitmapAddr.emitRawPointer(CGF)}; + MCDCCondBitmapAddr.getPointer()}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args); } @@ -1284,8 +1283,7 @@ void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr, - llvm::Value *Val, - CodeGenFunction &CGF) { + llvm::Value *Val) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1314,7 +1312,7 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), Builder.getInt64(FunctionHash), Builder.getInt32(Branch.ID), - MCDCCondBitmapAddr.emitRawPointer(CGF), Val}; + MCDCCondBitmapAddr.getPointer(), Val}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update), Args); diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 9d66ffad6f43..036fbf6815a4 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -113,14 +113,12 @@ public: void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, llvm::Value *StepV); void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, - CodeGenFunction &CGF); + Address MCDCCondBitmapAddr); void emitMCDCParameters(CGBuilderTy &Builder); void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr); void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, llvm::Value *Val, - CodeGenFunction &CGF); + Address MCDCCondBitmapAddr, llvm::Value *Val); /// Return the region count for the counter at the given index. uint64_t getRegionCount(const Stmt *S) { diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index fd71317572f0..bdd53a192f82 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -307,6 +307,10 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase); + llvm::Constant * + getVTableAddressPointForConstExpr(BaseSubobject Base, + const CXXRecordDecl *VTableClass) override; + llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -642,7 +646,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( // Apply the adjustment and cast back to the original struct type // for consistency. - llvm::Value *This = ThisAddr.emitRawPointer(CGF); + llvm::Value *This = ThisAddr.getPointer(); This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj); ThisPtrForCall = This; @@ -846,7 +850,7 @@ llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( CGBuilderTy &Builder = CGF.Builder; // Apply the offset, which we assume is non-null. - return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr, + return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.getPointer(), MemPtr, "memptr.offset"); } @@ -1241,7 +1245,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, CGF.getPointerAlign()); // Apply the offset. - llvm::Value *CompletePtr = Ptr.emitRawPointer(CGF); + llvm::Value *CompletePtr = Ptr.getPointer(); CompletePtr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset); @@ -1478,8 +1482,7 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastCall( computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity()); // Emit the call to __dynamic_cast. - llvm::Value *Args[] = {ThisAddr.emitRawPointer(CGF), SrcRTTI, DestRTTI, - OffsetHint}; + llvm::Value *Args[] = {ThisAddr.getPointer(), SrcRTTI, DestRTTI, OffsetHint}; llvm::Value *Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), Args); @@ -1568,7 +1571,7 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast( VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy)); llvm::Value *Success = CGF.Builder.CreateICmpEQ( VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl)); - llvm::Value *Result = ThisAddr.emitRawPointer(CGF); + llvm::Value *Result = ThisAddr.getPointer(); if (!Offset->isZero()) Result = CGF.Builder.CreateInBoundsGEP( CGF.CharTy, Result, @@ -1608,7 +1611,7 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top"); } // Finally, add the offset to the pointer. - return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.emitRawPointer(CGF), + return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.getPointer(), OffsetToTop); } @@ -1789,8 +1792,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), - ThisTy, VTT, VTTTy, nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, + nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1949,6 +1952,11 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( CGF.getPointerAlign()); } +llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( + BaseSubobject Base, const CXXRecordDecl *VTableClass) { + return getVTableAddressPoint(Base, VTableClass); +} + llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); @@ -2080,8 +2088,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( ThisTy = D->getDestroyedType(); } - CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, - nullptr, QualType(), nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, + QualType(), nullptr); return nullptr; } @@ -2154,7 +2162,7 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, int64_t VirtualAdjustment, bool IsReturnAdjustment) { if (!NonVirtualAdjustment && !VirtualAdjustment) - return InitialPtr.emitRawPointer(CGF); + return InitialPtr.getPointer(); Address V = InitialPtr.withElementType(CGF.Int8Ty); @@ -2187,10 +2195,10 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, CGF.getPointerAlign()); } // Adjust our pointer. - ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getElementType(), - V.emitRawPointer(CGF), Offset); + ResultPtr = CGF.Builder.CreateInBoundsGEP( + V.getElementType(), V.getPointer(), Offset); } else { - ResultPtr = V.emitRawPointer(CGF); + ResultPtr = V.getPointer(); } // In a derived-to-base conversion, the non-virtual adjustment is @@ -2276,7 +2284,7 @@ Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie"); - CGF.Builder.CreateCall(F, NumElementsPtr.emitRawPointer(CGF)); + CGF.Builder.CreateCall(F, NumElementsPtr.getPointer()); } // Finally, compute a pointer to the actual data buffer by skipping @@ -2307,7 +2315,7 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, llvm::FunctionType::get(CGF.SizeTy, CGF.UnqualPtrTy, false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie"); - return CGF.Builder.CreateCall(F, numElementsPtr.emitRawPointer(CGF)); + return CGF.Builder.CreateCall(F, numElementsPtr.getPointer()); } CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { @@ -2619,7 +2627,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // Call __cxa_guard_release. This cannot throw. CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), - guardAddr.emitRawPointer(CGF)); + guardAddr.getPointer()); } else if (D.isLocalVarDecl()) { // For local variables, store 1 into the first byte of the guard variable // after the object initialization completes so that initialization is @@ -3112,10 +3120,10 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, LValue LV; if (VD->getType()->isReferenceType()) - LV = CGF.MakeNaturalAlignRawAddrLValue(CallVal, LValType); + LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType); else - LV = CGF.MakeRawAddrLValue(CallVal, LValType, - CGF.getContext().getDeclAlign(VD)); + LV = CGF.MakeAddrLValue(CallVal, LValType, + CGF.getContext().getDeclAlign(VD)); // FIXME: need setObjCGCLValueClass? return LV; } @@ -4596,7 +4604,7 @@ static void InitCatchParam(CodeGenFunction &CGF, CGF.Builder.CreateStore(Casted, ExnPtrTmp); // Bind the reference to the temporary. - AdjustedExn = ExnPtrTmp.emitRawPointer(CGF); + AdjustedExn = ExnPtrTmp.getPointer(); } } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index d38a26940a3c..172c4c937b97 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -327,6 +327,10 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; + llvm::Constant * + getVTableAddressPointForConstExpr(BaseSubobject Base, + const CXXRecordDecl *VTableClass) override; + llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -933,7 +937,7 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, } CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); - CPI->setArgOperand(2, var.getObjectAddress(CGF).emitRawPointer(CGF)); + CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); CGF.EHStack.pushCleanup(NormalCleanup, CPI); CGF.EmitAutoVarCleanups(var); } @@ -970,7 +974,7 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, llvm::Value *Offset = GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP( - Value.getElementType(), Value.emitRawPointer(CGF), Offset); + Value.getElementType(), Value.getPointer(), Offset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); return std::make_tuple(Address(Ptr, CGF.Int8Ty, VBaseAlign), Offset, @@ -1007,7 +1011,7 @@ llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, llvm::Type *StdTypeInfoPtrTy) { std::tie(ThisPtr, std::ignore, std::ignore) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); - llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.emitRawPointer(CGF)); + llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()); return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); } @@ -1029,7 +1033,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastCall( llvm::Value *Offset; std::tie(This, Offset, std::ignore) = performBaseAdjustment(CGF, This, SrcRecordTy); - llvm::Value *ThisPtr = This.emitRawPointer(CGF); + llvm::Value *ThisPtr = This.getPointer(); Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); // PVOID __RTDynamicCast( @@ -1061,7 +1065,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, llvm::FunctionCallee Function = CGF.CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), "__RTCastToVoid"); - llvm::Value *Args[] = {Value.emitRawPointer(CGF)}; + llvm::Value *Args[] = {Value.getPointer()}; return CGF.EmitRuntimeCall(Function, Args); } @@ -1489,7 +1493,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( llvm::Value *VBaseOffset = GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); llvm::Value *VBasePtr = CGF.Builder.CreateInBoundsGEP( - Result.getElementType(), Result.emitRawPointer(CGF), VBaseOffset); + Result.getElementType(), Result.getPointer(), VBaseOffset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); Result = Address(VBasePtr, CGF.Int8Ty, VBaseAlign); @@ -1656,8 +1660,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, llvm::Value *Implicit = getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating); // = nullptr - CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), - ThisTy, + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, /*ImplicitParam=*/Implicit, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1788,6 +1791,13 @@ MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, return VFTablesMap[ID]; } +llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( + BaseSubobject Base, const CXXRecordDecl *VTableClass) { + llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); + assert(VFTable && "Couldn't find a vftable for the given base?"); + return VFTable; +} + llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { // getAddrOfVTable may return 0 if asked to get an address of a vtable which @@ -2003,9 +2013,8 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( } This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = - CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, - ImplicitParam, Context.IntTy, CE); + RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } @@ -2203,13 +2212,13 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This, const ThisAdjustment &TA) { if (TA.isEmpty()) - return This.emitRawPointer(CGF); + return This.getPointer(); This = This.withElementType(CGF.Int8Ty); llvm::Value *V; if (TA.Virtual.isEmpty()) { - V = This.emitRawPointer(CGF); + V = This.getPointer(); } else { assert(TA.Virtual.Microsoft.VtordispOffset < 0); // Adjust the this argument based on the vtordisp value. @@ -2218,7 +2227,7 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); VtorDispPtr = VtorDispPtr.withElementType(CGF.Int32Ty); llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); - V = CGF.Builder.CreateGEP(This.getElementType(), This.emitRawPointer(CGF), + V = CGF.Builder.CreateGEP(This.getElementType(), This.getPointer(), CGF.Builder.CreateNeg(VtorDisp)); // Unfortunately, having applied the vtordisp means that we no @@ -2255,11 +2264,11 @@ llvm::Value * MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const ReturnAdjustment &RA) { if (RA.isEmpty()) - return Ret.emitRawPointer(CGF); + return Ret.getPointer(); Ret = Ret.withElementType(CGF.Int8Ty); - llvm::Value *V = Ret.emitRawPointer(CGF); + llvm::Value *V = Ret.getPointer(); if (RA.Virtual.Microsoft.VBIndex) { assert(RA.Virtual.Microsoft.VBIndex > 0); int32_t IntSize = CGF.getIntSize().getQuantity(); @@ -2574,7 +2583,7 @@ struct ResetGuardBit final : EHScopeStack::Cleanup { struct CallInitThreadAbort final : EHScopeStack::Cleanup { llvm::Value *Guard; - CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {} + CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} void Emit(CodeGenFunction &CGF, Flags flags) override { // Calling _Init_thread_abort will reset the guard's state. @@ -3114,8 +3123,8 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, llvm::Value **VBPtrOut) { CGBuilderTy &Builder = CGF.Builder; // Load the vbtable pointer from the vbptr in the instance. - llvm::Value *VBPtr = Builder.CreateInBoundsGEP( - CGM.Int8Ty, This.emitRawPointer(CGF), VBPtrOffset, "vbptr"); + llvm::Value *VBPtr = Builder.CreateInBoundsGEP(CGM.Int8Ty, This.getPointer(), + VBPtrOffset, "vbptr"); if (VBPtrOut) *VBPtrOut = VBPtr; @@ -3194,7 +3203,7 @@ llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( Builder.CreateBr(SkipAdjustBB); CGF.EmitBlock(SkipAdjustBB); llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); - Phi->addIncoming(Base.emitRawPointer(CGF), OriginalBB); + Phi->addIncoming(Base.getPointer(), OriginalBB); Phi->addIncoming(AdjustedBase, VBaseAdjustBB); return Phi; } @@ -3229,7 +3238,7 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - Addr = Base.emitRawPointer(CGF); + Addr = Base.getPointer(); } // Apply the offset, which we assume is non-null. @@ -3517,7 +3526,7 @@ CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - ThisPtrForCall = This.emitRawPointer(CGF); + ThisPtrForCall = This.getPointer(); } if (NonVirtualBaseAdjustment) @@ -4436,7 +4445,10 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { llvm::GlobalVariable *TI = getThrowInfo(ThrowType); // Call into the runtime to throw the exception. - llvm::Value *Args[] = {AI.emitRawPointer(CGF), TI}; + llvm::Value *Args[] = { + AI.getPointer(), + TI + }; CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); } diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index b1dfe5bf8f27..6893b50a3cfe 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -295,11 +295,6 @@ public: /// Get the AST address space for alloca. virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; } - Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, - LangAS SrcAddr, LangAS DestAddr, - llvm::Type *DestTy, - bool IsNonNull = false) const; - /// Perform address space cast of an expression of pointer type. /// \param V is the LLVM value to be casted to another address space. /// \param SrcAddr is the language address space of \p V. diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index 7dce5042c3dc..8718f1ecf3a7 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -85,7 +85,7 @@ private: LValue Src) { llvm::Value *Handle = nullptr; llvm::Constant *C = - llvm::dyn_cast(Src.getAddress(CGF).emitRawPointer(CGF)); + llvm::dyn_cast(Src.getAddress(CGF).getPointer()); // Lookup `addrspacecast` through the constant pointer if any. if (auto *ASC = llvm::dyn_cast_or_null(C)) C = llvm::cast(ASC->getPointerOperand()); diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 362add30b435..00b04723f17d 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -513,10 +513,9 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8); llvm::Value *RegOffset = Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity())); - RegAddr = Address(Builder.CreateInBoundsGEP( - CGF.Int8Ty, RegAddr.emitRawPointer(CGF), RegOffset), - DirectTy, - RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); + RegAddr = Address( + Builder.CreateInBoundsGEP(CGF.Int8Ty, RegAddr.getPointer(), RegOffset), + DirectTy, RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); // Increase the used-register count. NumRegs = @@ -552,7 +551,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Round up address of argument to alignment CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); if (Align > OverflowAreaAlign) { - llvm::Value *Ptr = OverflowArea.emitRawPointer(CGF); + llvm::Value *Ptr = OverflowArea.getPointer(); OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align), OverflowArea.getElementType(), Align); } @@ -561,7 +560,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Increase the overflow area. OverflowArea = Builder.CreateConstInBoundsByteGEP(OverflowArea, Size); - Builder.CreateStore(OverflowArea.emitRawPointer(CGF), OverflowAreaAddr); + Builder.CreateStore(OverflowArea.getPointer(), OverflowAreaAddr); CGF.EmitBranch(Cont); } diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index 9025a633f328..a337a52a94ec 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -326,7 +326,7 @@ Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update VAList. Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); - Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); + Builder.CreateStore(NextPtr.getPointer(), VAListAddr); return ArgAddr.withElementType(ArgTy); } diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index deaafc85a315..6eb0c6ef2f7d 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -306,7 +306,7 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update overflow_arg_area_ptr pointer llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( - OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), + OverflowArgArea.getElementType(), OverflowArgArea.getPointer(), PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); @@ -382,9 +382,10 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, Address MemAddr = RawMemAddr.withElementType(DirectTy); // Update overflow_arg_area_ptr pointer - llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( - OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), - PaddedSizeV, "overflow_arg_area"); + llvm::Value *NewOverflowArgArea = + CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), + OverflowArgArea.getPointer(), PaddedSizeV, + "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); CGF.EmitBranch(ContBlock); diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index 88edb781a947..aeb48f851e16 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -180,7 +180,7 @@ Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Increment the VAList. if (!ArgSize.isZero()) { Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize); - Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr); + Builder.CreateStore(APN.getPointer(), VAListAddr); } return Val; diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index aa20c758d84a..3a90eee5f1c9 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -575,7 +575,7 @@ public: // Emit code to generate this result as a Value *. std::string asValue() override { if (AddressType) - return "(" + varname() + ".emitRawPointer(*this))"; + return "(" + varname() + ".getPointer())"; return Result::asValue(); } bool hasIntegerValue() const override { return Immediate; } diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 2e2ec9a1c830..2a0c1e9e8c44 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -2708,7 +2708,6 @@ public: IRBuilder(const IRBuilder &) = delete; InserterTy &getInserter() { return Inserter; } - const InserterTy &getInserter() const { return Inserter; } }; template -- GitLab From 1095f71bdfe25778c169954f249819bc5b553c91 Mon Sep 17 00:00:00 2001 From: smanna12 Date: Wed, 27 Mar 2024 20:20:22 -0500 Subject: [PATCH 151/541] [NFC][Clang] Fix potential dereferencing of nullptr (#86759) This patch replaces dyn_cast<> with cast<> to resolve potential static analyzer bugs for 1. Dereferencing a pointer issue with nullptr GVar when calling addAttribute() in AIXTargetCodeGenInfo::setTargetAttributes(clang::Decl const *, llvm::GlobalValue *, clang::CodeGen::CodeGenModule &). 2. Dereferencing a pointer issue with nullptr GG when calling getCorrespondingConstructor() in DeclareImplicitDeductionGuidesForTypeAlias(clang::Sema &, clang::TypeAliasTemplateDecl *, clang::SourceLocation). 3. Dereferencing a pointer issue with nullptr CurrentBT when calling getKind() in ComplexExprEmitter::GetHigherPrecisionFPType(clang::QualType). --- clang/lib/CodeGen/CGExprComplex.cpp | 2 +- clang/lib/CodeGen/Targets/PPC.cpp | 2 +- clang/lib/Sema/SemaTemplate.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index b873bc6737bb..c3774d0cb75e 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -289,7 +289,7 @@ public: const BinOpInfo &Op); QualType GetHigherPrecisionFPType(QualType ElementType) { - const auto *CurrentBT = dyn_cast(ElementType); + const auto *CurrentBT = cast(ElementType); switch (CurrentBT->getKind()) { case BuiltinType::Kind::Float16: return CGF.getContext().FloatTy; diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 00b04723f17d..3eadb19bd205 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -274,7 +274,7 @@ void AIXTargetCodeGenInfo::setTargetAttributes( if (!isa(GV)) return; - auto *GVar = dyn_cast(GV); + auto *GVar = cast(GV); auto GVId = GV->getName(); // Is this a global variable specified by the user as toc-data? diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 005529a53270..aab72dbaf48c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2974,7 +2974,7 @@ void DeclareImplicitDeductionGuidesForTypeAlias( if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration( F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), Sema::CodeSynthesisContext::BuildingDeductionGuides)) { - auto *GG = dyn_cast(FPrime); + auto *GG = cast(FPrime); buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList, GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), GG->getTypeSourceInfo(), -- GitLab From 0c1c0d53931636331b59a03ed08f70936835399c Mon Sep 17 00:00:00 2001 From: Jerry Wu Date: Thu, 28 Mar 2024 01:32:27 +0000 Subject: [PATCH 152/541] [MLIR] Add patterns to bubble-up pack and push-down unpack through collapse/expand shape ops (#85297) Add DataLayoutPropagation patterns to bubble-up pack and push-down unpack through collapse/expand shape ops. --------- Co-authored-by: Quinn Dawkins --- .../Transforms/DataLayoutPropagation.cpp | 303 +++++++++++++++++- .../Linalg/data-layout-propagation.mlir | 160 +++++++++ 2 files changed, 462 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp index 5ceb85e7d990..7fd88dec71d4 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @@ -17,6 +17,7 @@ #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/IR/Dominance.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/Debug.h" #include @@ -552,6 +553,305 @@ private: ControlPropagationFn controlFn; }; +/// Project dimsPos to the inner-most non-unit dim pos with reassocIndices. +/// +/// For example, given dimsPos [0, 2], reassocIndices [[0, 1], [2, 3]], and +/// targetShape [16, 16, 32, 1], it returns [1, 2]. Because for pos 0, the +/// inner-most projected dim in pos [0, 1] is 1. And for pos 2, the inner-most +/// non-unit projected dims in pos [2, 3] is 2. +/// +/// If all candidates in a reassociation are unit dims, it chooses the +/// inner-most dim pos. +static SmallVector +projectToInnerMostNonUnitDimsPos(ArrayRef dimsPos, + ArrayRef reassocIndices, + ArrayRef targetShape) { + SmallVector projectedDimsPos; + for (auto pos : dimsPos) { + // In the case all dims are unit, this will return the inner-most one. + int64_t projectedPos = reassocIndices[pos].back(); + for (auto i : llvm::reverse(reassocIndices[pos])) { + int64_t dim = targetShape[i]; + if (dim > 1 || ShapedType::isDynamic(dim)) { + projectedPos = i; + break; + } + } + projectedDimsPos.push_back(projectedPos); + } + return projectedDimsPos; +} + +/// Check if all dims in dimsPos are divisible by the corresponding tile sizes. +static bool isDimsDivisibleByTileSizes(ArrayRef dimsPos, + ArrayRef shape, + ArrayRef tileSizes) { + for (auto [pos, tileSize] : llvm::zip_equal(dimsPos, tileSizes)) { + int64_t dim = shape[pos]; + if (ShapedType::isDynamic(dim) || (dim % tileSize) != 0) + return false; + } + return true; +} + +/// Permutate the reassociation indices and reindex them in the sequence order. +/// Returns the next dim pos in the sequence. +/// +/// For example, given reassocIndices [[0, 1], [2]] and permutation [1, 0], it +/// applies the permutation to get [[2], [0, 1]] and reindexes the indices into +/// [[0], [1, 2]]. +static int64_t applyPermutationAndReindexReassoc( + SmallVector &reassocIndices, + ArrayRef permutation) { + applyPermutationToVector(reassocIndices, permutation); + int64_t nextPos = 0; + for (ReassociationIndices &indices : reassocIndices) { + for (auto &index : indices) { + index = nextPos; + nextPos += 1; + } + } + return nextPos; +} + +/// Bubble up pack op through collapse shape op when the packed dims can be +/// projected to the dims before collapsing. This is possible when the inner +/// tile sizes can divide the projected dims. +/// +/// For example: +/// +/// %collapsed = tensor.collapse_shape %in [[0, 1], 2] +/// : tensor into tensor +/// %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] +/// inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %empty +/// : tensor -> tensor +/// +/// can be transformed into: +/// +/// %pack = tensor.pack %in outer_dims_perm = [1, 2] +/// inner_dims_pos = [1, 2] inner_tiles = [8, 1] into %empty +/// : tensor -> tensor +/// %collapsed = tensor.collapse_shape %pack [[0, 1], 2, 3, 4] +/// : tensor into tensor +static LogicalResult +bubbleUpPackOpThroughCollapseShape(tensor::CollapseShapeOp collapseOp, + tensor::PackOp packOp, + PatternRewriter &rewriter) { + SmallVector innerTileSizes = packOp.getStaticTiles(); + ArrayRef innerDimsPos = packOp.getInnerDimsPos(); + ArrayRef outerDimsPerm = packOp.getOuterDimsPerm(); + + ArrayRef srcShape = collapseOp.getSrcType().getShape(); + SmallVector reassocIndices = + collapseOp.getReassociationIndices(); + // Project inner tile pos to the dim pos before collapsing. For example, if + // dims [x, y] is collapsed into [z], packing on dim z can be projected back + // to pack on dim y. + // + // Project to inner-most non-unit dims to increase the chance that they can be + // divided by the inner tile sizes. This is correct because for [..., x, 1], + // packing on dim 1 is equivalent to packing on dim x. + SmallVector projectedInnerDimsPos = + projectToInnerMostNonUnitDimsPos(innerDimsPos, reassocIndices, srcShape); + + if (!isDimsDivisibleByTileSizes(projectedInnerDimsPos, srcShape, + innerTileSizes)) { + return failure(); + } + // Expand the outer dims permutation with the associated source dims for the + // new permutation after bubbling. This is because moving a collapsed dim is + // equivalent to moving the associated source dims together. + SmallVector newOuterDimsPerm; + for (auto outerPos : outerDimsPerm) { + newOuterDimsPerm.insert(newOuterDimsPerm.end(), + reassocIndices[outerPos].begin(), + reassocIndices[outerPos].end()); + } + + auto emptyOp = tensor::PackOp::createDestinationTensor( + rewriter, packOp.getLoc(), collapseOp.getSrc(), packOp.getMixedTiles(), + projectedInnerDimsPos, newOuterDimsPerm); + auto newPackOp = rewriter.create( + packOp.getLoc(), collapseOp.getSrc(), emptyOp, projectedInnerDimsPos, + packOp.getMixedTiles(), packOp.getPaddingValue(), newOuterDimsPerm); + + SmallVector newReassocIndices = reassocIndices; + // First apply the permutation on the reassociations of the outer dims. + // For example given the permutation [1, 0], the reassociations [[0, 1], [2]] + // -> [[0], [1, 2]] + int64_t nextPos = + applyPermutationAndReindexReassoc(newReassocIndices, outerDimsPerm); + // Then add direct mapping for the inner tile dims. + for (size_t i = 0; i < innerDimsPos.size(); ++i) { + newReassocIndices.push_back({nextPos}); + nextPos += 1; + } + + auto newCollapseOp = rewriter.create( + collapseOp.getLoc(), packOp.getType(), newPackOp, newReassocIndices); + rewriter.replaceOp(packOp, newCollapseOp); + + return success(); +} + +class BubbleUpPackOpThroughReshapeOp final + : public OpRewritePattern { +public: + BubbleUpPackOpThroughReshapeOp(MLIRContext *context, ControlPropagationFn fun) + : OpRewritePattern(context), controlFn(std::move(fun)) {} + + LogicalResult matchAndRewrite(tensor::PackOp packOp, + PatternRewriter &rewriter) const override { + Operation *srcOp = packOp.getSource().getDefiningOp(); + // Currently only support when the pack op is the only user. + if (!srcOp || !(srcOp->getNumResults() == 1) || + !srcOp->getResult(0).hasOneUse()) { + return failure(); + } + // Currently only support static inner tile sizes. + if (llvm::any_of(packOp.getStaticTiles(), [](int64_t size) { + return ShapedType::isDynamic(size); + })) { + return failure(); + } + + // User controlled propagation function. + if (!controlFn(srcOp)) + return failure(); + + return TypeSwitch(srcOp) + .Case([&](tensor::CollapseShapeOp op) { + return bubbleUpPackOpThroughCollapseShape(op, packOp, rewriter); + }) + .Default([](Operation *) { return failure(); }); + } + +private: + ControlPropagationFn controlFn; +}; + +/// Push down unpack op through expand shape op when the packed dims can be +/// projected to the dims after expanding. This is possible when the inner tile +/// sizes can divide the projected dims. +/// +/// For example: +/// +/// %unpack = tensor.unpack %in outer_dims_perm = [0, 1] +/// inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %empty +/// : tensor -> tensor +/// %expanded = tensor.expand_shape %unpack [[0, 1], [2]] +/// : tensor into tensor +/// +/// can be transformed into: +/// +/// %expanded = tensor.expand_shape %ain [[0, 1], [2], [3], [4]] +/// : tensor into tensor +/// %unpack = tensor.unpack %expanded outer_dims_perm = [0, 1, 2] +/// inner_dims_pos = [1, 2] inner_tiles = [8, 8] into %empty +/// : tensor -> tensor +static LogicalResult +pushDownUnPackOpThroughExpandShape(tensor::UnPackOp unPackOp, + tensor::ExpandShapeOp expandOp, + PatternRewriter &rewriter) { + SmallVector innerTileSizes = unPackOp.getStaticTiles(); + ArrayRef innerDimsPos = unPackOp.getInnerDimsPos(); + ArrayRef outerDimsPerm = unPackOp.getOuterDimsPerm(); + + ArrayRef dstShape = expandOp.getType().getShape(); + SmallVector reassocIndices = + expandOp.getReassociationIndices(); + // Project inner tile pos to the dim pos after expanding. For example, if dims + // [z] is expanded into [x, y], unpacking on dim z can be projected to unpack + // on dim y. + // + // Project to inner-most non-unit dims to increase the chance that they can be + // divided by the inner tile sizes. This is correct because for [..., x, 1], + // unpacking on dim 1 is equivalent to unpacking on dim x. + SmallVector projectedInnerDimsPos = + projectToInnerMostNonUnitDimsPos(innerDimsPos, reassocIndices, dstShape); + + if (!isDimsDivisibleByTileSizes(projectedInnerDimsPos, dstShape, + innerTileSizes)) { + return failure(); + } + // Expand the outer dims permutation with the associated expanded dims for the + // new permutation after pushing. This is because moving a source dim is + // equivalent to moving the associated expanded dims together. + SmallVector newOuterDimsPerm; + for (auto outerPos : outerDimsPerm) { + newOuterDimsPerm.insert(newOuterDimsPerm.end(), + reassocIndices[outerPos].begin(), + reassocIndices[outerPos].end()); + } + + SmallVector newReassocIndices = reassocIndices; + // First apply the permutation on the reassociations of the outer dims. + // For example given the permutation [1, 0], the reassociations [[0, 1], [2]] + // -> [[0], [1, 2]] + int64_t nextPos = + applyPermutationAndReindexReassoc(newReassocIndices, outerDimsPerm); + // Then add direct mapping for the inner tile dims. + for (size_t i = 0; i < innerDimsPos.size(); ++i) { + newReassocIndices.push_back({nextPos}); + nextPos += 1; + } + + RankedTensorType newExpandType = + tensor::PackOp::inferPackedType(expandOp.getType(), innerTileSizes, + projectedInnerDimsPos, newOuterDimsPerm); + auto newExpandOp = rewriter.create( + expandOp.getLoc(), newExpandType, unPackOp.getSource(), + newReassocIndices); + + auto emptyOp = tensor::UnPackOp::createDestinationTensor( + rewriter, unPackOp.getLoc(), newExpandOp, unPackOp.getMixedTiles(), + projectedInnerDimsPos, newOuterDimsPerm); + auto newUnPackOp = rewriter.create( + unPackOp.getLoc(), newExpandOp.getResult(), emptyOp, + projectedInnerDimsPos, unPackOp.getMixedTiles(), newOuterDimsPerm); + rewriter.replaceOp(expandOp, newUnPackOp); + + return success(); +} + +class PushDownUnPackOpThroughReshapeOp final + : public OpRewritePattern { +public: + PushDownUnPackOpThroughReshapeOp(MLIRContext *context, + ControlPropagationFn fun) + : OpRewritePattern(context), controlFn(std::move(fun)) { + } + + LogicalResult matchAndRewrite(tensor::UnPackOp unPackOp, + PatternRewriter &rewriter) const override { + Value result = unPackOp.getResult(); + // Currently only support unpack op with the single user. + if (!result.hasOneUse()) { + return failure(); + } + // Currently only support static inner tile sizes. + if (llvm::any_of(unPackOp.getStaticTiles(), [](int64_t size) { + return ShapedType::isDynamic(size); + })) { + return failure(); + } + + Operation *consumerOp = *result.user_begin(); + // User controlled propagation function. + if (!controlFn(consumerOp)) + return failure(); + + return TypeSwitch(consumerOp) + .Case([&](tensor::ExpandShapeOp op) { + return pushDownUnPackOpThroughExpandShape(unPackOp, op, rewriter); + }) + .Default([](Operation *) { return failure(); }); + } + +private: + ControlPropagationFn controlFn; +}; + // TODO: Relax this restriction. We should unpack a generic op also // in the presence of multiple unpack ops as producers. /// Return the unpacked operand, if present, for the current generic op. @@ -774,6 +1074,7 @@ void mlir::linalg::populateDataLayoutPropagationPatterns( const ControlPropagationFn &controlPackUnPackPropagation) { patterns .insert( + BubbleUpPackOpThroughReshapeOp, PushDownUnPackOpThroughGenericOp, + PushDownUnPackThroughPadOp, PushDownUnPackOpThroughReshapeOp>( patterns.getContext(), controlPackUnPackPropagation); } diff --git a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir index e036695a2ac9..79d61ab757e3 100644 --- a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir +++ b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir @@ -905,3 +905,163 @@ func.func @unpack_different_destination_shape(%arg0: tensor<1x1x1080x1920x16xi32 // CHECK-SAME: inner_dims_pos = [0] inner_tiles = [16] // CHECK-SAME: into %[[UNPACK_NEW_DEST]] // CHECK: return %[[UNPACK]] : tensor<16x540x960xi32> + +// ----- + +func.func @bubble_up_pack_through_collapse(%1: tensor, %dim : index) -> tensor { + %collapsed = tensor.collapse_shape %1 [[0, 1], [2]] : tensor into tensor + %2 = tensor.empty(%dim) : tensor + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %2 : tensor -> tensor + func.return %pack : tensor +} +// CHECK-LABEL: func.func @bubble_up_pack_through_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [1, 2] inner_tiles = [8, 1] into %[[EMPTY]] : tensor -> tensor +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[PACK]] {{\[}}[0, 1], [2], [3], [4]] : tensor into tensor +// CHECK: return %[[COLLAPSED]] : tensor + +// ----- + +func.func @bubble_up_permuted_pack_through_collapse(%1: tensor<4x192x16x256xf32>) -> tensor<4x32x3072x8x1xf32> { + %collapsed = tensor.collapse_shape %1 [[0], [1, 2], [3]] : tensor<4x192x16x256xf32> into tensor<4x3072x256xf32> + %2 = tensor.empty() : tensor<4x32x3072x8x1xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 2, 1] inner_dims_pos = [2, 1] inner_tiles = [8, 1] into %2 : tensor<4x3072x256xf32> -> tensor<4x32x3072x8x1xf32> + func.return %pack : tensor<4x32x3072x8x1xf32> +} +// CHECK-LABEL: func.func @bubble_up_permuted_pack_through_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x32x192x16x8x1xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 3, 1, 2] inner_dims_pos = [3, 2] inner_tiles = [8, 1] into %[[EMPTY]] : tensor<4x192x16x256xf32> -> tensor<4x32x192x16x8x1xf32> +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %pack {{\[}}[0], [1], [2, 3], [4], [5]] : tensor<4x32x192x16x8x1xf32> into tensor<4x32x3072x8x1xf32> +// CHECK: return %[[COLLAPSED]] : tensor<4x32x3072x8x1xf32> + +// ----- + +func.func @bubble_up_pack_through_unit_collapse(%1: tensor<1x64x1x4xf32>) -> tensor<8x4x8x1xf32> { + %collapsed = tensor.collapse_shape %1 [[0, 1, 2], [3]] : tensor<1x64x1x4xf32> into tensor<64x4xf32> + %2 = tensor.empty() : tensor<8x4x8x1xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %2 : tensor<64x4xf32> -> tensor<8x4x8x1xf32> + func.return %pack : tensor<8x4x8x1xf32> +} +// CHECK-LABEL: func.func @bubble_up_pack_through_unit_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<1x8x1x4x8x1xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 1, 2, 3] inner_dims_pos = [1, 3] inner_tiles = [8, 1] into %[[EMPTY]] : tensor<1x64x1x4xf32> -> tensor<1x8x1x4x8x1xf32> +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[PACK]] {{\[}}[0, 1, 2], [3], [4], [5]] : tensor<1x8x1x4x8x1xf32> into tensor<8x4x8x1xf32> +// CHECK: return %[[COLLAPSED]] : tensor<8x4x8x1xf32> + +// ----- + +func.func @bubble_up_pack_through_collapse_on_outer_dims(%1: tensor, %dim : index) -> tensor { + %collapsed = tensor.collapse_shape %1 [[0, 1], [2]] : tensor into tensor + %2 = tensor.empty(%dim) : tensor + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [1] inner_tiles = [4] into %2 : tensor -> tensor + func.return %pack : tensor +} +// CHECK-LABEL: func.func @bubble_up_pack_through_collapse_on_outer_dims +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [2] inner_tiles = [4] into %[[EMPTY]] : tensor -> tensor +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[PACK]] {{\[}}[0, 1], [2], [3]] : tensor into tensor +// CHECK: return %[[COLLAPSED]] : tensor + +// ----- + +func.func @no_bubble_up_pack_through_non_divisible_collapse(%1: tensor<3072x64x4xf32>) -> tensor<384x32x8x8xf32> { + %collapsed = tensor.collapse_shape %1 [[0], [1, 2]] : tensor<3072x64x4xf32> into tensor<3072x256xf32> + %2 = tensor.empty() : tensor<384x32x8x8xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %2 : tensor<3072x256xf32> -> tensor<384x32x8x8xf32> + func.return %pack : tensor<384x32x8x8xf32> +} +// CHECK-LABEL: func.func @no_bubble_up_pack_through_non_divisible_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<3072x64x4xf32> into tensor<3072x256xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[COLLAPSED]] +// CHECK: return %[[PACK]] : tensor<384x32x8x8xf32> + +// ----- + +func.func @push_down_unpack_through_expand(%5: tensor, %dim: index) -> tensor { + %6 = tensor.empty(%dim) : tensor + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %6 : tensor -> tensor + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] : tensor into tensor + func.return %expanded : tensor +} +// CHECK-LABEL: func.func @push_down_unpack_through_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3], [4]] : tensor into tensor +// CHECK: %[[DIM:.+]] = tensor.dim %[[EXPANDED]], %[[C0]] : tensor +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED:.+]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [1, 2] inner_tiles = [8, 8] into %[[EMPTY]] : tensor -> tensor +// CHECK: return %[[UNPACK]] : tensor + +// ----- + +func.func @push_down_permuted_unpack_through_expand(%5: tensor<4x32x384x8x8xf32>) -> tensor<4x12x256x256xf32> { + %6 = tensor.empty() : tensor<4x3072x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 2, 1] inner_dims_pos = [2, 1] inner_tiles = [8, 8] into %6 : tensor<4x32x384x8x8xf32> -> tensor<4x3072x256xf32> + %expanded = tensor.expand_shape %unpack [[0], [1, 2], [3]] : tensor<4x3072x256xf32> into tensor<4x12x256x256xf32> + func.return %expanded : tensor<4x12x256x256xf32> +} +// CHECK-LABEL: @push_down_permuted_unpack_through_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1], [2, 3], [4], [5]] : tensor<4x32x384x8x8xf32> into tensor<4x32x12x32x8x8xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x12x256x256xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED]] outer_dims_perm = [0, 3, 1, 2] inner_dims_pos = [3, 2] inner_tiles = [8, 8] into %[[EMPTY]] : tensor<4x32x12x32x8x8xf32> -> tensor<4x12x256x256xf32> +// CHECK: return %[[UNPACK]] : tensor<4x12x256x256xf32> + +// ----- + +func.func @push_down_unpack_through_unit_expand(%5: tensor<6x32x8x8xf32>) -> tensor<3x16x1x256xf32> { + %6 = tensor.empty() : tensor<48x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %6 : tensor<6x32x8x8xf32> -> tensor<48x256xf32> + %expanded = tensor.expand_shape %unpack [[0, 1, 2], [3]] : tensor<48x256xf32> into tensor<3x16x1x256xf32> + func.return %expanded : tensor<3x16x1x256xf32> +} +// CHECK-LABEL: func.func @push_down_unpack_through_unit_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3], [4], [5]] : tensor<6x32x8x8xf32> into tensor<3x2x1x32x8x8xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x16x1x256xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED]] outer_dims_perm = [0, 1, 2, 3] inner_dims_pos = [1, 3] inner_tiles = [8, 8] into %[[EMPTY]] : tensor<3x2x1x32x8x8xf32> -> tensor<3x16x1x256xf32> +// CHECK: return %[[UNPACK]] : tensor<3x16x1x256xf32> + +// ----- + +func.func @push_down_unpack_through_expand_on_outer_dims(%5: tensor, %dim: index) -> tensor { + %6 = tensor.empty(%dim) : tensor + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [1] inner_tiles = [8] into %6 : tensor -> tensor + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] : tensor into tensor + func.return %expanded : tensor +} +// CHECK-LABEL: func.func @push_down_unpack_through_expand_on_outer_dims +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3]] : tensor into tensor +// CHECK: %[[DIM:.+]] = tensor.dim %[[EXPANDED]], %[[C0]] : tensor +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED:.+]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [2] inner_tiles = [8] into %[[EMPTY]] : tensor -> tensor +// CHECK: return %[[UNPACK]] : tensor + +// ----- + +func.func @no_push_down_unpack_through_non_divisible_expand(%5: tensor<384x32x8x8xf32>) -> tensor<256x12x256xf32> { + %6 = tensor.empty() : tensor<3072x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %6 : tensor<384x32x8x8xf32> -> tensor<3072x256xf32> + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] : tensor<3072x256xf32> into tensor<256x12x256xf32> + func.return %expanded : tensor<256x12x256xf32> +} +// CHECK-LABEL: func.func @no_push_down_unpack_through_non_divisible_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[ARG0]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[UNPACK]] {{\[}}[0, 1], [2]] : tensor<3072x256xf32> into tensor<256x12x256xf32> +// CHECK: return %[[EXPANDED]] : tensor<256x12x256xf32> -- GitLab From 443baed56c770aca050d27581d5d6f0c5c168285 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 27 Mar 2024 20:01:30 -0700 Subject: [PATCH 153/541] [ELF,test] Update tests that depend on --export-dynamic creating dynamic sections The CloudABI change from https://reviews.llvm.org/D30175 does not make sense. Update tests not to rely on the --export-dynamic behavior. --- lld/test/ELF/common-gc2.s | 8 +++++--- lld/test/ELF/executable-undefined-ignoreall.s | 2 -- .../ELF/relro-non-contiguous-script-data.s | 6 ++++-- lld/test/ELF/riscv-undefined-weak.s | 18 ++++++++---------- lld/test/ELF/x86-64-dyn-rel-error.s | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lld/test/ELF/common-gc2.s b/lld/test/ELF/common-gc2.s index fec1c4be86b5..1ecaef7d9af5 100644 --- a/lld/test/ELF/common-gc2.s +++ b/lld/test/ELF/common-gc2.s @@ -1,7 +1,9 @@ # REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t -# RUN: ld.lld -gc-sections -export-dynamic %t -o %t1 -# RUN: llvm-readobj --dyn-symbols %t1 | FileCheck %s +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 /dev/null -o %t2.o +# RUN: ld.lld -shared -soname=t2 %t2.o -o %t2.so +# RUN: ld.lld -gc-sections -export-dynamic %t.o %t2.so -o %t +# RUN: llvm-readobj --dyn-symbols %t | FileCheck %s # CHECK: Name: bar # CHECK: Name: foo diff --git a/lld/test/ELF/executable-undefined-ignoreall.s b/lld/test/ELF/executable-undefined-ignoreall.s index cc38e17cdf61..073b22bd8454 100644 --- a/lld/test/ELF/executable-undefined-ignoreall.s +++ b/lld/test/ELF/executable-undefined-ignoreall.s @@ -7,8 +7,6 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: ld.lld %t.o -o %t --unresolved-symbols=ignore-all -pie # RUN: llvm-readobj -r %t | FileCheck %s -# RUN: ld.lld %t.o -o %t --unresolved-symbols=ignore-all --export-dynamic -# RUN: llvm-readobj -r %t | FileCheck %s # CHECK: Relocations [ # CHECK-NEXT: Section ({{.*}}) .rela.plt { diff --git a/lld/test/ELF/relro-non-contiguous-script-data.s b/lld/test/ELF/relro-non-contiguous-script-data.s index fd485e89167f..530fc7c84eb9 100644 --- a/lld/test/ELF/relro-non-contiguous-script-data.s +++ b/lld/test/ELF/relro-non-contiguous-script-data.s @@ -1,19 +1,21 @@ // REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64 /dev/null -o %t2.o +// RUN: ld.lld -shared -soname=t2 %t2.o -o %t2.so // RUN: echo "SECTIONS { \ // RUN: .dynamic : { *(.dynamic) } \ // RUN: .non_ro : { . += 1; } \ // RUN: .jcr : { *(.jcr) } \ // RUN: } " > %t.script // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -// RUN: not ld.lld --export-dynamic %t.o -o /dev/null --script=%t.script 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %t2.so -o /dev/null --script=%t.script 2>&1 | FileCheck %s // RUN: echo "SECTIONS { \ // RUN: .dynamic : { *(.dynamic) } \ // RUN: .non_ro : { BYTE(1); } \ // RUN: .jcr : { *(.jcr) } \ // RUN: } " > %t2.script -// RUN: not ld.lld --export-dynamic %t.o -o /dev/null --script=%t2.script 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %t2.so -o /dev/null --script=%t2.script 2>&1 | FileCheck %s // CHECK: error: section: .jcr is not contiguous with other relro sections diff --git a/lld/test/ELF/riscv-undefined-weak.s b/lld/test/ELF/riscv-undefined-weak.s index 303a27f920c5..8a78e1f83833 100644 --- a/lld/test/ELF/riscv-undefined-weak.s +++ b/lld/test/ELF/riscv-undefined-weak.s @@ -1,4 +1,6 @@ # REQUIRES: riscv +# RUN: llvm-mc -filetype=obj -triple=riscv64 /dev/null -o %t2.o +# RUN: ld.lld -shared -soname=t2 %t2.o -o %t2.so # RUN: llvm-mc -filetype=obj -triple=riscv64 -riscv-asm-relax-branches=0 %s -o %t.o # RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELOC %s @@ -6,7 +8,7 @@ # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,PC %s # RUN: llvm-readelf -x .data %t | FileCheck --check-prefixes=HEX,HEX-WITHOUT-PLT %s -# RUN: ld.lld -e absolute %t.o -o %t --export-dynamic +# RUN: ld.lld -e absolute %t.o -o %t %t2.so # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,PLT %s # RUN: llvm-readelf -x .data %t | FileCheck --check-prefixes=HEX,HEX-WITH-PLT %s @@ -34,11 +36,11 @@ absolute: # CHECK-LABEL: : # CHECK-NEXT: 11{{...}}: auipc a1, 0xfffef # PC-NEXT: addi a1, a1, -0x160 -# PLT-NEXT: addi a1, a1, -0x318 +# PLT-NEXT: addi a1, a1, -0x290 # CHECK-LABEL: <.Lpcrel_hi1>: # CHECK-NEXT: 11{{...}}: auipc t1, 0xfffef # PC-NEXT: sd a2, -0x166(t1) -# PLT-NEXT: sd a2, -0x31e(t1) +# PLT-NEXT: sd a2, -0x296(t1) relative: la a1, target sd a2, target+2, t1 @@ -62,7 +64,7 @@ relative: ## We create a PLT entry and redirect the reference to it. # PLT-LABEL: : # PLT-NEXT: auipc ra, 0x0 -# PLT-NEXT: jalr 0x38(ra) +# PLT-NEXT: jalr 0x30(ra) # PLT-NEXT: [[#%x,ADDR:]]: # PLT-SAME: j 0x[[#ADDR]] # PLT-NEXT: [[#%x,ADDR:]]: @@ -84,12 +86,8 @@ branch: ## A plt entry is created for target, so this is the offset between the ## plt entry and this address. ## -## S = 0x11360 (the address of the plt entry for target) -## A = 0 -## P = 0x1343c (the address of `.`) -## -## S - A + P = -0x0x20dc = 0xffffdf24 -# HEX-WITH-PLT-SAME: 24dfffff +## S - A + P = -0x0x20ec = 0xffffdf14 +# HEX-WITH-PLT-SAME: 14dfffff .data .p2align 3 diff --git a/lld/test/ELF/x86-64-dyn-rel-error.s b/lld/test/ELF/x86-64-dyn-rel-error.s index a03adf89072f..1590045312d4 100644 --- a/lld/test/ELF/x86-64-dyn-rel-error.s +++ b/lld/test/ELF/x86-64-dyn-rel-error.s @@ -19,7 +19,7 @@ # CHECK-NOT: error: # RUN: ld.lld --noinhibit-exec %t.o %t2.so -o /dev/null 2>&1 | FileCheck --check-prefix=WARN %s -# RUN: not ld.lld --export-dynamic --unresolved-symbols=ignore-all %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=WARN %s +# RUN: not ld.lld --export-dynamic --unresolved-symbols=ignore-all %t.o %t2.so -o /dev/null 2>&1 | FileCheck --check-prefix=WARN %s # WARN: relocation R_X86_64_32 cannot be used against symbol 'zed'; recompile with -fPIC # WARN: relocation R_X86_64_PC32 cannot be used against symbol 'zed'; recompile with -fPIC -- GitLab From 070d7af0c56b993806fa47f77b607b1849a2172f Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 27 Mar 2024 20:04:59 -0700 Subject: [PATCH 154/541] [ELF] --export-dynamic: don't create dynamic sections for non-PIC static links The CloudABI (removed from Clang Driver) change from https://reviews.llvm.org/D29982 does not make sense. GNU ld and gold don't create dynamic sections for a non-PIC static link when --export-dynamic is specified. Creating dynamic sections is harmful in this scenario because we would consider undefined weak symbols preemptible and generate GLOB_DAT relocations, breaking the expectation that non-PIC static links only contain IRELATIVE relocations. In addition, there are other options that export symbols (--export-dynamic-symbol, --dynamic-list, etc). It does not make sense to special case --export-dynamic. --- lld/ELF/Driver.cpp | 10 ++----- lld/test/ELF/static-with-export-dynamic.s | 32 ----------------------- lld/test/ELF/weak-undef.s | 9 ++++--- 3 files changed, 7 insertions(+), 44 deletions(-) delete mode 100644 lld/test/ELF/static-with-export-dynamic.s diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index f14a2376601b..b43da7727e22 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2724,14 +2724,8 @@ template void LinkerDriver::link(opt::InputArgList &args) { parseFiles(files, armCmseImpLib); - // Now that we have every file, we can decide if we will need a - // dynamic symbol table. - // We need one if we were asked to export dynamic symbols or if we are - // producing a shared library. - // We also need one if any shared libraries are used and for pie executables - // (probably because the dynamic linker needs it). - config->hasDynSymTab = - !ctx.sharedFiles.empty() || config->isPic || config->exportDynamic; + // Create dynamic sections for dynamic linking and static PIE. + config->hasDynSymTab = !ctx.sharedFiles.empty() || config->isPic; script->addScriptReferencedSymbolsToSymTable(); diff --git a/lld/test/ELF/static-with-export-dynamic.s b/lld/test/ELF/static-with-export-dynamic.s deleted file mode 100644 index b0349b85e303..000000000000 --- a/lld/test/ELF/static-with-export-dynamic.s +++ /dev/null @@ -1,32 +0,0 @@ -// REQUIRES: x86 -// RUN: llvm-mc -filetype=obj -triple=i686-unknown-cloudabi %s -o %t.o -// RUN: ld.lld --export-dynamic %t.o -o %t -// RUN: llvm-readobj --dyn-syms %t | FileCheck %s - -// Ensure that a dynamic symbol table is present when --export-dynamic -// is passed in, even when creating statically linked executables. -// -// CHECK: DynamicSymbols [ -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: -// CHECK-NEXT: Value: 0x0 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Local -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: Undefined -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: _start -// CHECK-NEXT: Value: -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: .text -// CHECK-NEXT: } -// CHECK-NEXT: ] - -.global _start -_start: - ret diff --git a/lld/test/ELF/weak-undef.s b/lld/test/ELF/weak-undef.s index 3a9d5f462c21..21488023a79e 100644 --- a/lld/test/ELF/weak-undef.s +++ b/lld/test/ELF/weak-undef.s @@ -16,10 +16,11 @@ # RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend # RELOC-NEXT: {{.*}} 0000000100000001 R_X86_64_64 0000000000000000 foo + 0 -# COMMON: Symbol table '.dynsym' contains 2 entries: -# COMMON-NEXT: Num: Value Size Type Bind Vis Ndx Name -# COMMON-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND -# COMMON-NEXT: 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND foo +# NORELOC-NOT: Symbol table '.dynsym' +# RELOC: Symbol table '.dynsym' contains 2 entries: +# RELOC-NEXT: Num: Value Size Type Bind Vis Ndx Name +# RELOC-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +# RELOC-NEXT: 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND foo # COMMON: Hex dump of section '.data': # COMMON-NEXT: {{.*}} 00000000 00000000 # COMMON-EMPTY: -- GitLab From 2c7610cc43cd70192a0ed5eac58471c50045c6de Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Wed, 27 Mar 2024 20:40:01 -0700 Subject: [PATCH 155/541] [nfc]Make InstrProfSymtab non-copyable and non-movable (#86882) - The direct use case (in [1]) is to add `llvm::IntervalMap` [2] and the allocator required by IntervalMap ctor [3] to class `InstrProfSymtab` as owned members. The allocator class doesn't have a move-assignment operator; and it's going to take much effort to implement move-assignment operator for the allocator class such that the enclosing class is movable. - There is only one use of compiler-generated move-assignment operator in the repo, which is in CoverageMappingReader.cpp. Luckily it's possible to use std::unique_ptr instead, so did the change. [1] https://github.com/llvm/llvm-project/pull/66825 [2] https://github.com/llvm/llvm-project/blob/4c2f68840e984b0f111779c46845ac00e3a7547d/llvm/include/llvm/ADT/IntervalMap.h#L936 [3] https://github.com/llvm/llvm-project/blob/4c2f68840e984b0f111779c46845ac00e3a7547d/llvm/include/llvm/ADT/IntervalMap.h#L1041 --- .../Coverage/CoverageMappingReader.h | 17 +++++---- llvm/include/llvm/ProfileData/InstrProf.h | 7 ++++ .../Coverage/CoverageMappingReader.cpp | 35 ++++++++++--------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h index 346ca4ad2eb3..f05b90114d75 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -184,7 +184,7 @@ public: private: std::vector Filenames; std::vector MappingRecords; - InstrProfSymtab ProfileNames; + std::unique_ptr ProfileNames; size_t CurrentRecord = 0; std::vector FunctionsFilenames; std::vector Expressions; @@ -195,8 +195,9 @@ private: // D69471, which can split up function records into multiple sections on ELF. FuncRecordsStorage FuncRecords; - BinaryCoverageReader(FuncRecordsStorage &&FuncRecords) - : FuncRecords(std::move(FuncRecords)) {} + BinaryCoverageReader(std::unique_ptr Symtab, + FuncRecordsStorage &&FuncRecords) + : ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)) {} public: BinaryCoverageReader(const BinaryCoverageReader &) = delete; @@ -209,12 +210,10 @@ public: SmallVectorImpl *BinaryIDs = nullptr); static Expected> - createCoverageReaderFromBuffer(StringRef Coverage, - FuncRecordsStorage &&FuncRecords, - InstrProfSymtab &&ProfileNames, - uint8_t BytesInAddress, - llvm::endianness Endian, - StringRef CompilationDir = ""); + createCoverageReaderFromBuffer( + StringRef Coverage, FuncRecordsStorage &&FuncRecords, + std::unique_ptr ProfileNamesPtr, uint8_t BytesInAddress, + llvm::endianness Endian, StringRef CompilationDir = ""); Error readNextRecord(CoverageMappingRecord &Record) override; }; diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h index 25ec06a73920..612c444faec6 100644 --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -471,6 +471,13 @@ private: public: InstrProfSymtab() = default; + // Not copyable or movable. + // Consider std::unique_ptr for move. + InstrProfSymtab(const InstrProfSymtab &) = delete; + InstrProfSymtab &operator=(const InstrProfSymtab &) = delete; + InstrProfSymtab(InstrProfSymtab &&) = delete; + InstrProfSymtab &operator=(InstrProfSymtab &&) = delete; + /// Create InstrProfSymtab from an object file section which /// contains function PGO names. When section may contain raw /// string data or string data in compressed form. This method diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index d32846051083..445b48067a97 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -894,31 +894,34 @@ static Error readCoverageMappingData( Expected> BinaryCoverageReader::createCoverageReaderFromBuffer( StringRef Coverage, FuncRecordsStorage &&FuncRecords, - InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress, + std::unique_ptr ProfileNamesPtr, uint8_t BytesInAddress, llvm::endianness Endian, StringRef CompilationDir) { - std::unique_ptr Reader( - new BinaryCoverageReader(std::move(FuncRecords))); - Reader->ProfileNames = std::move(ProfileNames); + if (ProfileNamesPtr == nullptr) + return make_error(coveragemap_error::malformed, + "Caller must provide ProfileNames"); + std::unique_ptr Reader(new BinaryCoverageReader( + std::move(ProfileNamesPtr), std::move(FuncRecords))); + InstrProfSymtab &ProfileNames = *Reader->ProfileNames; StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer(); if (BytesInAddress == 4 && Endian == llvm::endianness::little) { if (Error E = readCoverageMappingData( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) { if (Error E = readCoverageMappingData( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) { if (Error E = readCoverageMappingData( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) { if (Error E = readCoverageMappingData( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else return make_error( @@ -963,8 +966,8 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { if (Data.size() < ProfileNamesSize) return make_error(coveragemap_error::malformed, "the size of ProfileNames is too big"); - InstrProfSymtab ProfileNames; - if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) + auto ProfileNames = std::make_unique(); + if (Error E = ProfileNames->create(Data.substr(0, ProfileNamesSize), Address)) return std::move(E); Data = Data.substr(ProfileNamesSize); @@ -1099,7 +1102,7 @@ loadBinaryFormat(std::unique_ptr Bin, StringRef Arch, OF->isLittleEndian() ? llvm::endianness::little : llvm::endianness::big; // Look for the sections that we are interested in. - InstrProfSymtab ProfileNames; + auto ProfileNames = std::make_unique(); std::vector NamesSectionRefs; // If IPSK_name is not found, fallback to search for IPK_covname, which is // used when binary correlation is enabled. @@ -1116,7 +1119,7 @@ loadBinaryFormat(std::unique_ptr Bin, StringRef Arch, return make_error( coveragemap_error::malformed, "the size of coverage mapping section is not one"); - if (Error E = ProfileNames.create(NamesSectionRefs.back())) + if (Error E = ProfileNames->create(NamesSectionRefs.back())) return std::move(E); auto CoverageSection = lookupSections(*OF, IPSK_covmap); -- GitLab From 056b4043543cbc9e4ecad183db185bd26324b5b1 Mon Sep 17 00:00:00 2001 From: Job Henandez Lara Date: Wed, 27 Mar 2024 20:55:12 -0700 Subject: [PATCH 156/541] [libc][NFC] refactor fmin and fmax (#86718) Hello, So, I worked on the fmaximum and fminimum functions recently and the reviewers suggested the structure: ``` if (bitsx ...) return ...; if (bitsy ..) return ... return ...; ``` So I went ahead and did the same for fmin and fmax. I hope this isnt an issue for you all. thanks. --------- Co-authored-by: Job Hernandez --- libc/src/__support/FPUtil/BasicOperations.h | 24 +++++++++------------ 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index f746d7ac6ad4..a47931bb3390 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -30,36 +30,32 @@ template , int> = 0> LIBC_INLINE T fmin(T x, T y) { const FPBits bitx(x), bity(y); - if (bitx.is_nan()) { + if (bitx.is_nan()) return y; - } else if (bity.is_nan()) { + if (bity.is_nan()) return x; - } else if (bitx.sign() != bity.sign()) { + if (bitx.sign() != bity.sign()) // To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and // y has different signs and both are not NaNs, we return the number // with negative sign. - return (bitx.is_neg()) ? x : y; - } else { - return (x < y ? x : y); - } + return bitx.is_neg() ? x : y; + return x < y ? x : y; } template , int> = 0> LIBC_INLINE T fmax(T x, T y) { FPBits bitx(x), bity(y); - if (bitx.is_nan()) { + if (bitx.is_nan()) return y; - } else if (bity.is_nan()) { + if (bity.is_nan()) return x; - } else if (bitx.sign() != bity.sign()) { + if (bitx.sign() != bity.sign()) // To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and // y has different signs and both are not NaNs, we return the number // with positive sign. - return (bitx.is_neg() ? y : x); - } else { - return (x > y ? x : y); - } + return bitx.is_neg() ? y : x; + return x > y ? x : y; } template , int> = 0> -- GitLab From e766f87b922933d6b1aefcfd24e5111162369e2e Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 27 Mar 2024 21:22:57 -0700 Subject: [PATCH 157/541] [clang-format] Handle C++ Core Guidelines suppression tags (#86458) Fixes #86451. --- clang/lib/Format/TokenAnnotator.cpp | 4 ++++ clang/unittests/Format/FormatTest.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 4c83a7a3a323..b9144cf55452 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4827,6 +4827,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, Right.is(TT_TemplateOpener)) { return true; } + if (Left.is(tok::identifier) && Right.is(tok::numeric_constant) && + Right.TokenText[0] == '.') { + return false; + } } else if (Style.isProto()) { if (Right.is(tok::period) && Left.isOneOf(Keywords.kw_optional, Keywords.kw_required, diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index d1e977dfa66a..33dec7dae319 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12075,6 +12075,7 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) { verifyFormat("SomeType s [[gnu::unused]] (InitValue);"); verifyFormat("SomeType s [[using gnu: unused]] (InitValue);"); verifyFormat("[[gsl::suppress(\"clang-tidy-check-name\")]] void f() {}"); + verifyFormat("[[suppress(type.5)]] int uninitialized_on_purpose;"); verifyFormat("void f() [[deprecated(\"so sorry\")]];"); verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);"); -- GitLab From d9e3e11ae57612ec61f6fcab4afc27d8d0ff5841 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Wed, 27 Mar 2024 21:23:37 -0700 Subject: [PATCH 158/541] [clang-format] Exit clang-format-diff only after all diffs are printed (#86776) See https://github.com/llvm/llvm-project/pull/70883#issuecomment-2020811077. --- clang/tools/clang-format/clang-format-diff.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/tools/clang-format/clang-format-diff.py b/clang/tools/clang-format/clang-format-diff.py index 0a2c24743678..3a74b90e7315 100755 --- a/clang/tools/clang-format/clang-format-diff.py +++ b/clang/tools/clang-format/clang-format-diff.py @@ -138,6 +138,7 @@ def main(): ) # Reformat files containing changes in place. + has_diff = False for filename, lines in lines_by_file.items(): if args.i and args.verbose: print("Formatting {}".format(filename)) @@ -169,7 +170,7 @@ def main(): stdout, stderr = p.communicate() if p.returncode != 0: - sys.exit(p.returncode) + return p.returncode if not args.i: with open(filename) as f: @@ -185,9 +186,12 @@ def main(): ) diff_string = "".join(diff) if len(diff_string) > 0: + has_diff = True sys.stdout.write(diff_string) - sys.exit(1) + + if has_diff: + return 1 if __name__ == "__main__": - main() + sys.exit(main()) -- GitLab From 6b7ecc7979134c152ee5f8286f904bba18f41185 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Thu, 28 Mar 2024 04:41:29 +0000 Subject: [PATCH 159/541] Revert "[WebAssembly] Remove threwValue comparison after __wasm_setjmp_test (#86633)" This reverts commit 52431fdb1ab8d29be078edd55250e06381e4b6b0. The PR assumed `__threwValue` couldn't be 0, but it could be when the thrown thing is not a longjmp but an exception, so that `if` check was actually necessary. --- .../WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp | 8 +++++--- llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll | 7 ++++--- llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll | 4 +++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp index 0788d0c3a721..027ee1086bf4 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -153,7 +153,7 @@ /// %__THREW__.val = __THREW__; /// __THREW__ = 0; /// %__threwValue.val = __threwValue; -/// if (%__THREW__.val != 0) { +/// if (%__THREW__.val != 0 & %__threwValue.val != 0) { /// %label = __wasm_setjmp_test(%__THREW__.val, functionInvocationId); /// if (%label == 0) /// emscripten_longjmp(%__THREW__.val, %__threwValue.val); @@ -712,10 +712,12 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp( BasicBlock *ThenBB1 = BasicBlock::Create(C, "if.then1", F); BasicBlock *ElseBB1 = BasicBlock::Create(C, "if.else1", F); BasicBlock *EndBB1 = BasicBlock::Create(C, "if.end", F); + Value *ThrewCmp = IRB.CreateICmpNE(Threw, getAddrSizeInt(M, 0)); Value *ThrewValue = IRB.CreateLoad(IRB.getInt32Ty(), ThrewValueGV, ThrewValueGV->getName() + ".val"); - Value *ThrewCmp = IRB.CreateICmpNE(Threw, getAddrSizeInt(M, 0)); - IRB.CreateCondBr(ThrewCmp, ThenBB1, ElseBB1); + Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0)); + Value *Cmp1 = IRB.CreateAnd(ThrewCmp, ThrewValueCmp, "cmp1"); + IRB.CreateCondBr(Cmp1, ThenBB1, ElseBB1); // Generate call.em.longjmp BB once and share it within the function if (!CallEmLongjmpBB) { diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll index d88f42a4dc58..32942cd92e68 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll @@ -22,8 +22,10 @@ entry: to label %try.cont unwind label %lpad ; CHECK: entry.split.split: -; CHECK: %__threwValue.val = load i32, ptr @__threwValue -; CHECK-NEXT: %[[CMP:.*]] = icmp ne i32 %__THREW__.val, 0 +; CHECK: %[[CMP0:.*]] = icmp ne i32 %__THREW__.val, 0 +; CHECK-NEXT: %__threwValue.val = load i32, ptr @__threwValue +; CHECK-NEXT: %[[CMP1:.*]] = icmp ne i32 %__threwValue.val, 0 +; CHECK-NEXT: %[[CMP:.*]] = and i1 %[[CMP0]], %[[CMP1]] ; CHECK-NEXT: br i1 %[[CMP]], label %if.then1, label %if.else1 ; This is exception checking part. %if.else1 leads here @@ -119,7 +121,6 @@ if.end: ; preds = %entry ; CHECK-NEXT: unreachable ; CHECK: normal: -; CHECK-NEXT: %__threwValue.val = load i32, ptr @__threwValue, align 4 ; CHECK-NEXT: icmp ne i32 %__THREW__.val, 0 return: ; preds = %if.end, %entry diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll index dca4c59d7c87..27ec95a2c462 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll @@ -37,8 +37,10 @@ entry: ; CHECK-NEXT: call cc{{.*}} void @__invoke_void_[[PTR]]_i32(ptr @emscripten_longjmp, [[PTR]] %[[JMPBUF]], i32 1) ; CHECK-NEXT: %[[__THREW__VAL:.*]] = load [[PTR]], ptr @__THREW__ ; CHECK-NEXT: store [[PTR]] 0, ptr @__THREW__ +; CHECK-NEXT: %[[CMP0:.*]] = icmp ne [[PTR]] %__THREW__.val, 0 ; CHECK-NEXT: %[[THREWVALUE_VAL:.*]] = load i32, ptr @__threwValue -; CHECK-NEXT: %[[CMP:.*]] = icmp ne [[PTR]] %__THREW__.val, 0 +; CHECK-NEXT: %[[CMP1:.*]] = icmp ne i32 %[[THREWVALUE_VAL]], 0 +; CHECK-NEXT: %[[CMP:.*]] = and i1 %[[CMP0]], %[[CMP1]] ; CHECK-NEXT: br i1 %[[CMP]], label %if.then1, label %if.else1 ; CHECK: entry.split.split.split: -- GitLab From a41bfea5c049737e9c51e8d9a5769f72fbc55f59 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 27 Mar 2024 22:10:11 -0700 Subject: [PATCH 160/541] [MC] Simplify ELFObjectWriter. NFC And fix `if (hasRelocationAddend())` to `usesRela` to properly treat SHT_LLVM_CALL_GRAPH_PROFILE as SHT_REL. The incorrect does not cause a problem because the synthesized SHT_LLVM_CALL_GRAPH_PROFILE has zero addends. --- llvm/lib/MC/ELFObjectWriter.cpp | 36 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index f4c6cbc8dd44..005521bad6e0 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -141,7 +141,6 @@ struct ELFWriter { // TargetObjectWriter wrappers. bool is64Bit() const; - bool usesRela(const MCSectionELF &Sec) const; uint64_t align(Align Alignment); @@ -260,6 +259,7 @@ public: void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) override; + bool usesRela(const MCSectionELF &Sec) const; void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; @@ -394,11 +394,6 @@ bool ELFWriter::is64Bit() const { return OWriter.TargetObjectWriter->is64Bit(); } -bool ELFWriter::usesRela(const MCSectionELF &Sec) const { - return OWriter.hasRelocationAddend() && - Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE; -} - // Emit the ELF header. void ELFWriter::writeHeader(const MCAssembler &Asm) { // ELF Header @@ -825,24 +820,22 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, if (OWriter.Relocations[&Sec].empty()) return nullptr; - const StringRef SectionName = Sec.getName(); - bool Rela = usesRela(Sec); - std::string RelaSectionName = Rela ? ".rela" : ".rel"; - RelaSectionName += SectionName; + unsigned Flags = ELF::SHF_INFO_LINK; + if (Sec.getFlags() & ELF::SHF_GROUP) + Flags = ELF::SHF_GROUP; + const StringRef SectionName = Sec.getName(); + const bool Rela = OWriter.usesRela(Sec); unsigned EntrySize; if (Rela) EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); else EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); - unsigned Flags = ELF::SHF_INFO_LINK; - if (Sec.getFlags() & ELF::SHF_GROUP) - Flags = ELF::SHF_GROUP; - - MCSectionELF *RelaSection = Ctx.createELFRelSection( - RelaSectionName, Rela ? ELF::SHT_RELA : ELF::SHT_REL, Flags, EntrySize, - Sec.getGroup(), &Sec); + MCSectionELF *RelaSection = + Ctx.createELFRelSection(((Rela ? ".rela" : ".rel") + SectionName), + Rela ? ELF::SHT_RELA : ELF::SHT_REL, Flags, + EntrySize, Sec.getGroup(), &Sec); RelaSection->setAlignment(is64Bit() ? Align(8) : Align(4)); return RelaSection; } @@ -938,11 +931,11 @@ void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, void ELFWriter::writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec) { std::vector &Relocs = OWriter.Relocations[&Sec]; + const bool Rela = OWriter.usesRela(Sec); // Sort the relocation entries. MIPS needs this. OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs); - const bool Rela = usesRela(Sec); if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { for (const ELFRelocationEntry &Entry : Relocs) { uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0; @@ -1499,7 +1492,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined() ? C + Layout.getSymbolOffset(*SymA) : C; - if (hasRelocationAddend()) { + if (usesRela(FixupSection)) { Addend = FixedValue; FixedValue = 0; } @@ -1528,6 +1521,11 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, Relocations[&FixupSection].push_back(Rec); } +bool ELFObjectWriter::usesRela(const MCSectionELF &Sec) const { + return hasRelocationAddend() && + Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE; +} + bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB, bool InSet, bool IsPCRel) const { -- GitLab From f8bab38b6dd02f2cd3acc28521d0ccb3186ef616 Mon Sep 17 00:00:00 2001 From: Lei Wang Date: Wed, 27 Mar 2024 22:27:22 -0700 Subject: [PATCH 161/541] [CSSPGO] Fix the issue of missing callee profile matches (#85715) Two fixes related to the callee/inlinee profile: 1. Fix the bug that the matching results are missing to distribute to the callee profiles (should be pass-by-reference). 2. Narrow imported function matching to checksum mismatched functions. More context: before we run matchings for all imported functions even checksums are matched, however, after we fix 1), we got a regression, it's likely due to the matching is not no-op for checksum matched function, so we want to make it consistent to only run matching for checksum mismatched (imported)functions. Since the metadata(pseudo_probe_desc) are dropped for imported function, we leverage the function attribute mechanism and add a new function attribute(`profile-checksum-mismatch`) to transfer the info from pre-link to post-link. --- .../Utils/SampleProfileLoaderBaseImpl.h | 25 +++---- llvm/lib/Transforms/IPO/SampleProfile.cpp | 46 +++++++++---- .../pseudo-probe-callee-profile-mismatch.prof | 16 +++++ .../csspgo-profile-checksum-mismatch-attr.ll | 67 +++++++++++++++++++ .../pseudo-probe-callee-profile-mismatch.ll | 63 +++++++++++++++++ ...pseudo-probe-stale-profile-matching-lto.ll | 2 +- .../pseudo-probe-stale-profile-matching.ll | 2 + 7 files changed, 194 insertions(+), 27 deletions(-) create mode 100644 llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-callee-profile-mismatch.prof create mode 100644 llvm/test/Transforms/SampleProfile/csspgo-profile-checksum-mismatch-attr.ll create mode 100644 llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll diff --git a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h index 66814d395273..bd7496a799c5 100644 --- a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h +++ b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h @@ -86,9 +86,12 @@ template <> struct IRTraits { // SampleProfileProber. class PseudoProbeManager { DenseMap GUIDToProbeDescMap; + const ThinOrFullLTOPhase LTOPhase; public: - PseudoProbeManager(const Module &M) { + PseudoProbeManager(const Module &M, + ThinOrFullLTOPhase LTOPhase = ThinOrFullLTOPhase::None) + : LTOPhase(LTOPhase) { if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) { for (const auto *Operand : FuncInfo->operands()) { @@ -126,17 +129,15 @@ public: bool profileIsValid(const Function &F, const FunctionSamples &Samples) const { const auto *Desc = getDesc(F); - if (!Desc) { - LLVM_DEBUG(dbgs() << "Probe descriptor missing for Function " - << F.getName() << "\n"); - return false; - } - if (Desc->getFunctionHash() != Samples.getFunctionHash()) { - LLVM_DEBUG(dbgs() << "Hash mismatch for Function " << F.getName() - << "\n"); - return false; - } - return true; + assert((LTOPhase != ThinOrFullLTOPhase::ThinLTOPostLink || !Desc || + profileIsHashMismatched(*Desc, Samples) == + F.hasFnAttribute("profile-checksum-mismatch")) && + "In post-link, profile checksum matching state doesn't match " + "function 'profile-checksum-mismatch' attribute."); + // The desc for import function is unavailable. Check the function attribute + // for mismatch. + return (!Desc && !F.hasFnAttribute("profile-checksum-mismatch")) || + (Desc && !profileIsHashMismatched(*Desc, Samples)); } }; diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index 2cbef8a7ae61..7545a92c114e 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -453,6 +453,7 @@ class SampleProfileMatcher { Module &M; SampleProfileReader &Reader; const PseudoProbeManager *ProbeManager; + const ThinOrFullLTOPhase LTOPhase; SampleProfileMap FlattenedProfiles; // For each function, the matcher generates a map, of which each entry is a // mapping from the source location of current build to the source location in @@ -504,8 +505,9 @@ class SampleProfileMatcher { public: SampleProfileMatcher(Module &M, SampleProfileReader &Reader, - const PseudoProbeManager *ProbeManager) - : M(M), Reader(Reader), ProbeManager(ProbeManager){}; + const PseudoProbeManager *ProbeManager, + ThinOrFullLTOPhase LTOPhase) + : M(M), Reader(Reader), ProbeManager(ProbeManager), LTOPhase(LTOPhase){}; void runOnModule(); void clearMatchingData() { // Do not clear FuncMappings, it stores IRLoc to ProfLoc remappings which @@ -521,7 +523,7 @@ private: return &It->second; return nullptr; } - void runOnFunction(const Function &F); + void runOnFunction(Function &F); void findIRAnchors(const Function &F, std::map &IRAnchors); void findProfileAnchors( @@ -1911,15 +1913,22 @@ bool SampleProfileLoader::emitAnnotations(Function &F) { bool Changed = false; if (FunctionSamples::ProfileIsProbeBased) { - if (!ProbeManager->profileIsValid(F, *Samples)) { + LLVM_DEBUG({ + if (!ProbeManager->getDesc(F)) + dbgs() << "Probe descriptor missing for Function " << F.getName() + << "\n"; + }); + + if (ProbeManager->profileIsValid(F, *Samples)) { + ++NumMatchedProfile; + } else { + ++NumMismatchedProfile; LLVM_DEBUG( dbgs() << "Profile is invalid due to CFG mismatch for Function " << F.getName() << "\n"); - ++NumMismatchedProfile; if (!SalvageStaleProfile) return false; } - ++NumMatchedProfile; } else { if (getFunctionLoc(F) == 0) return false; @@ -2185,7 +2194,7 @@ bool SampleProfileLoader::doInitialization(Module &M, // Load pseudo probe descriptors for probe-based function samples. if (Reader->profileIsProbeBased()) { - ProbeManager = std::make_unique(M); + ProbeManager = std::make_unique(M, LTOPhase); if (!ProbeManager->moduleIsProbed(M)) { const char *Msg = "Pseudo-probe-based profile requires SampleProfileProbePass"; @@ -2197,8 +2206,8 @@ bool SampleProfileLoader::doInitialization(Module &M, if (ReportProfileStaleness || PersistProfileStaleness || SalvageStaleProfile) { - MatchingManager = - std::make_unique(M, *Reader, ProbeManager.get()); + MatchingManager = std::make_unique( + M, *Reader, ProbeManager.get(), LTOPhase); } return true; @@ -2452,7 +2461,7 @@ void SampleProfileMatcher::runStaleProfileMatching( } } -void SampleProfileMatcher::runOnFunction(const Function &F) { +void SampleProfileMatcher::runOnFunction(Function &F) { // We need to use flattened function samples for matching. // Unlike IR, which includes all callsites from the source code, the callsites // in profile only show up when they are hit by samples, i,e. the profile @@ -2481,8 +2490,16 @@ void SampleProfileMatcher::runOnFunction(const Function &F) { // support for pseudo-probe. if (SalvageStaleProfile && FunctionSamples::ProfileIsProbeBased && !ProbeManager->profileIsValid(F, *FSFlattened)) { - // The matching result will be saved to IRToProfileLocationMap, create a new - // map for each function. + // For imported functions, the checksum metadata(pseudo_probe_desc) are + // dropped, so we leverage function attribute(profile-checksum-mismatch) to + // transfer the info: add the attribute during pre-link phase and check it + // during post-link phase(see "profileIsValid"). + if (FunctionSamples::ProfileIsProbeBased && + LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) + F.addFnAttr("profile-checksum-mismatch"); + + // The matching result will be saved to IRToProfileLocationMap, create a + // new map for each function. auto &IRToProfileLocationMap = getIRToProfileLocationMap(F); runStaleProfileMatching(F, IRAnchors, ProfileAnchors, IRToProfileLocationMap); @@ -2758,8 +2775,9 @@ void SampleProfileMatcher::distributeIRToProfileLocationMap( FS.setIRToProfileLocationMap(&(ProfileMappings->second)); } - for (auto &Inlinees : FS.getCallsiteSamples()) { - for (auto FS : Inlinees.second) { + for (auto &Callees : + const_cast(FS.getCallsiteSamples())) { + for (auto &FS : Callees.second) { distributeIRToProfileLocationMap(FS.second); } } diff --git a/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-callee-profile-mismatch.prof b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-callee-profile-mismatch.prof new file mode 100644 index 000000000000..76a8fc9d19a8 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-callee-profile-mismatch.prof @@ -0,0 +1,16 @@ +main:252:0 + 1: 0 + 2: 50 + 5: 50 + 7: bar:102 + 1: 51 + 2: baz:51 + 1: 51 + !CFGChecksum: 4294967295 + !Attributes: 3 + !CFGChecksum: 281479271677951 + !Attributes: 2 + !CFGChecksum: 281582081721716 +bar:1:1 + 1: 1 + !CFGChecksum: 281479271677951 diff --git a/llvm/test/Transforms/SampleProfile/csspgo-profile-checksum-mismatch-attr.ll b/llvm/test/Transforms/SampleProfile/csspgo-profile-checksum-mismatch-attr.ll new file mode 100644 index 000000000000..df56b55dcdf3 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/csspgo-profile-checksum-mismatch-attr.ll @@ -0,0 +1,67 @@ +; REQUIRES: x86_64-linux +; REQUIRES: asserts +; RUN: opt < %s -passes='thinlto-pre-link' -pgo-kind=pgo-sample-use-pipeline -sample-profile-file=%S/Inputs/pseudo-probe-callee-profile-mismatch.prof -pass-remarks=inline -S -o %t 2>&1 | FileCheck %s --check-prefix=INLINE +; RUN: FileCheck %s < %t +; RUN: FileCheck %s < %t --check-prefix=MERGE + + +; Make sure bar is inlined into main for attr merging verification. +; INLINE: 'bar' inlined into 'main' + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @baz() #0 { +entry: + ret i32 0 +} + +define i32 @bar() #0 !dbg !11 { +; CHECK: define {{.*}} @bar() {{.*}} #[[#BAR_ATTR:]] ! +entry: + %call = call i32 @baz() + ret i32 0 +} + +define i32 @main() #0 { +; MERGE: define {{.*}} @main() {{.*}} #[[#MAIN_ATTR:]] ! +entry: + br label %for.cond + +for.cond: ; preds = %for.cond, %entry + %call = call i32 @bar(), !dbg !14 + br label %for.cond +} + +; CHECK: attributes #[[#BAR_ATTR]] = {{{.*}} "profile-checksum-mismatch" {{.*}}} + +; Verify the attribute is not merged into the caller. +; MERGE-NOT: attributes #[[#MAIN_ATTR]] = {{{.*}} "profile-checksum-mismatch" {{.*}}} + +attributes #0 = { "use-sample-profile" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7} +!llvm.pseudo_probe_desc = !{!8, !9, !10} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/home", checksumkind: CSK_MD5, checksum: "0df0c950a93a603a7d13f0a9d4623642") +!2 = !{!3} +!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!4 = distinct !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!5 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !6) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{i64 7546896869197086323, i64 4294967295, !"baz"} +!9 = !{i64 -2012135647395072713, i64 281530612780802, !"bar"} +!10 = !{i64 -2624081020897602054, i64 281582081721716, !"main"} +!11 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !12, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) +!12 = distinct !DISubroutineType(types: !13) +!13 = !{} +!14 = !DILocation(line: 15, column: 10, scope: !15) +!15 = !DILexicalBlockFile(scope: !16, file: !1, discriminator: 186646591) +!16 = distinct !DILexicalBlock(scope: !17, file: !1, line: 14, column: 40) +!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 14, column: 3) +!18 = distinct !DILexicalBlock(scope: !19, file: !1, line: 14, column: 3) +!19 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 12, type: !20, scopeLine: 13, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) +!20 = !DISubroutineType(types: !13) diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll new file mode 100644 index 000000000000..e00b737cae4e --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll @@ -0,0 +1,63 @@ +; REQUIRES: x86_64-linux +; REQUIRES: asserts +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-callee-profile-mismatch.prof --salvage-stale-profile -S --debug-only=sample-profile,sample-profile-impl -pass-remarks=inline 2>&1 | FileCheck %s + + +; CHECK: Run stale profile matching for bar +; CHECK: Callsite with callee:baz is matched from 4 to 2 +; CHECK: 'baz' inlined into 'main' to match profiling context with (cost=always): preinliner at callsite bar:3:8.4 @ main:3:10.7 + +; CHECK: Probe descriptor missing for Function bar +; CHECK: Profile is invalid due to CFG mismatch for Function bar + + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @main() #0 { + %1 = call i32 @bar(), !dbg !13 + ret i32 0 +} + +define available_externally i32 @bar() #1 !dbg !21 { + %1 = call i32 @baz(), !dbg !23 + ret i32 0 +} + +define available_externally i32 @baz() #0 !dbg !25 { + ret i32 0 +} + +attributes #0 = { "use-sample-profile" } +attributes #1 = { "profile-checksum-mismatch" "use-sample-profile" } + +!llvm.dbg.cu = !{!0, !7, !9} +!llvm.module.flags = !{!11} +!llvm.pseudo_probe_desc = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/home/test", checksumkind: CSK_MD5, checksum: "7220f1a2d70ff869f1a6ab7958e3c393") +!2 = !{!3} +!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!4 = distinct !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!5 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !6) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !8, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!8 = !DIFile(filename: "test1.v1.c", directory: "/home/test", checksumkind: CSK_MD5, checksum: "76696bd6bfe16a9f227fe03cfdb6a82c") +!9 = distinct !DICompileUnit(language: DW_LANG_C11, file: !10, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!10 = !DIFile(filename: "test2.c", directory: "/home/test", checksumkind: CSK_MD5, checksum: "553093afc026f9c73562eb3b0c5b7532") +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i64 -2624081020897602054, i64 281582081721716, !"main"} +!13 = !DILocation(line: 8, column: 10, scope: !14) +!14 = !DILexicalBlockFile(scope: !15, file: !1, discriminator: 186646591) +!15 = distinct !DILexicalBlock(scope: !16, file: !1, line: 7, column: 40) +!16 = distinct !DILexicalBlock(scope: !17, file: !1, line: 7, column: 3) +!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 7, column: 3) +!18 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 5, type: !19, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !20) +!19 = distinct !DISubroutineType(types: !20) +!20 = !{} +!21 = distinct !DISubprogram(name: "bar", scope: !8, file: !8, line: 3, type: !22, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !7, retainedNodes: !20) +!22 = !DISubroutineType(types: !20) +!23 = !DILocation(line: 6, column: 8, scope: !24) +!24 = !DILexicalBlockFile(scope: !21, file: !8, discriminator: 186646567) +!25 = distinct !DISubprogram(name: "baz", scope: !10, file: !10, line: 1, type: !22, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !9, retainedNodes: !20) diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll index 55225b415d4a..270beee4ebc2 100644 --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll @@ -106,7 +106,7 @@ define available_externally dso_local i32 @bar(i32 noundef %0) local_unnamed_add ret i32 %2, !dbg !132 } -attributes #0 = { nounwind uwtable "disable-tail-calls"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "use-sample-profile" } +attributes #0 = { nounwind uwtable "disable-tail-calls"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "use-sample-profile" "profile-checksum-mismatch"} attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } attributes #3 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable "disable-tail-calls"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "use-sample-profile" } diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll index 89477ea5fecf..29877fb22a2c 100644 --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll @@ -48,6 +48,8 @@ ; } ; } +; Verify not running profile matching for checksum matched function. +; CHECK-NOT: Run stale profile matching for bar ; CHECK: Run stale profile matching for main -- GitLab From ed801ab460f387a4e125ccfaa5ccdea1dd499ebf Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Wed, 27 Mar 2024 23:11:16 -0700 Subject: [PATCH 162/541] [Transforms] Fix an unused variable warning llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h:89:28: error: private field 'LTOPhase' is not used [-Werror,-Wunused-private-field] --- llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h index bd7496a799c5..048b97c34ee2 100644 --- a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h +++ b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h @@ -134,6 +134,7 @@ public: F.hasFnAttribute("profile-checksum-mismatch")) && "In post-link, profile checksum matching state doesn't match " "function 'profile-checksum-mismatch' attribute."); + (void)LTOPhase; // The desc for import function is unavailable. Check the function attribute // for mismatch. return (!Desc && !F.hasFnAttribute("profile-checksum-mismatch")) || -- GitLab From 5dfc446d7545d7ac960e20be362bd9935f390827 Mon Sep 17 00:00:00 2001 From: hchandel <165007698+hchandel@users.noreply.github.com> Date: Thu, 28 Mar 2024 11:43:47 +0530 Subject: [PATCH 163/541] [RISCV] Remove Unnecessary Semicolon. NFC (#86911) Removes Unnecessary Semicolon Co-authored-by: Harsh Chandel --- llvm/lib/Target/RISCV/RISCVISelLowering.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index c11b1464757c..ace5b3fd2b95 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -1000,7 +1000,7 @@ private: /// RISC-V doesn't have flags so it's better to perform the and/or in a GPR. bool shouldNormalizeToSelectSequence(LLVMContext &, EVT) const override { return false; - }; + } /// For available scheduling models FDIV + two independent FMULs are much /// faster than two FDIVs. -- GitLab From e5b93994941245d35827b62ec91a537dfb52c243 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 27 Mar 2024 23:59:24 -0700 Subject: [PATCH 164/541] [libc] Move baremetal write_to_stderr implementation to io.cpp (#86890) This is required to avoid multiple definitions error. --- .../__support/OSUtil/baremetal/CMakeLists.txt | 1 + libc/src/__support/OSUtil/baremetal/io.cpp | 22 +++++++++++++++++++ libc/src/__support/OSUtil/baremetal/io.h | 7 +----- 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 libc/src/__support/OSUtil/baremetal/io.cpp diff --git a/libc/src/__support/OSUtil/baremetal/CMakeLists.txt b/libc/src/__support/OSUtil/baremetal/CMakeLists.txt index 23da40326bbb..e78301d104c1 100644 --- a/libc/src/__support/OSUtil/baremetal/CMakeLists.txt +++ b/libc/src/__support/OSUtil/baremetal/CMakeLists.txt @@ -1,6 +1,7 @@ add_object_library( baremetal_util SRCS + io.cpp quick_exit.cpp HDRS io.h diff --git a/libc/src/__support/OSUtil/baremetal/io.cpp b/libc/src/__support/OSUtil/baremetal/io.cpp new file mode 100644 index 000000000000..347c7d405b0a --- /dev/null +++ b/libc/src/__support/OSUtil/baremetal/io.cpp @@ -0,0 +1,22 @@ +//===---------- Baremetal implementation of IO utils ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "io.h" + +#include "src/__support/CPP/string_view.h" + +// This is intended to be provided by the vendor. +extern "C" void __llvm_libc_log_write(const char *msg, size_t len); + +namespace LIBC_NAMESPACE { + +void write_to_stderr(cpp::string_view msg) { + __llvm_libc_log_write(msg.data(), msg.size()); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/OSUtil/baremetal/io.h b/libc/src/__support/OSUtil/baremetal/io.h index a50c11d4aea1..87534641b1fa 100644 --- a/libc/src/__support/OSUtil/baremetal/io.h +++ b/libc/src/__support/OSUtil/baremetal/io.h @@ -13,12 +13,7 @@ namespace LIBC_NAMESPACE { -// This is intended to be provided by the vendor. -extern "C" void __llvm_libc_log_write(const char *msg, size_t len); - -void write_to_stderr(cpp::string_view msg) { - __llvm_libc_log_write(msg.data(), msg.size()); -} +void write_to_stderr(cpp::string_view msg); } // namespace LIBC_NAMESPACE -- GitLab From b7ac8fddb54816256fab70696ebc176717a391c3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Levytskyy Date: Thu, 28 Mar 2024 08:08:06 +0100 Subject: [PATCH 165/541] [SPIR-V] Improve type inference: deduce types of composite data structures (#86782) This PR improves type inference in general and deduces types of composite data structures in particular. Also added a way to insert a bitcast to make a fun call valid in case of arguments types mismatch due to opaque pointers type inference. The attached test `pointers/nested-struct-opaque-pointers.ll` demonstrates new capabilities: the SPIRV code emitted for this test is now (1) valid in a sense of data field types and (2) accepted by `spirv-val`. More strict LIT checks, support of more composite data structures and improvement of fun calls from the perspective of type correctness are main todo's at the moment. --- llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 25 +- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 216 +++++++++++++----- llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 80 +++++++ llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp | 108 ++++++++- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 +- llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 5 +- llvm/lib/Target/SPIRV/SPIRVUtils.h | 22 +- .../pointers/nested-struct-opaque-pointers.ll | 20 ++ .../SPIRV/pointers/struct-opaque-pointers.ll | 8 +- .../pointers/type-deduce-by-call-chain.ll | 7 +- 10 files changed, 412 insertions(+), 81 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/pointers/nested-struct-opaque-pointers.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index afdca01561b0..ad4e72a3128b 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -201,21 +201,30 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, if (!isPointerTy(OriginalArgType)) return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual); - // In case OriginalArgType is of pointer type, there are three possibilities: + Argument *Arg = F.getArg(ArgIdx); + Type *ArgType = Arg->getType(); + if (isTypedPointerTy(ArgType)) { + SPIRVType *ElementType = GR->getOrCreateSPIRVType( + cast(ArgType)->getElementType(), MIRBuilder); + return GR->getOrCreateSPIRVPointerType( + ElementType, MIRBuilder, + addressSpaceToStorageClass(getPointerAddressSpace(ArgType), ST)); + } + + // In case OriginalArgType is of untyped pointer type, there are three + // possibilities: // 1) This is a pointer of an LLVM IR element type, passed byval/byref. // 2) This is an OpenCL/SPIR-V builtin type if there is spv_assign_type - // intrinsic assigning a TargetExtType. + // intrinsic assigning a TargetExtType. // 3) This is a pointer, try to retrieve pointer element type from a // spv_assign_ptr_type intrinsic or otherwise use default pointer element // type. - Argument *Arg = F.getArg(ArgIdx); - if (HasPointeeTypeAttr(Arg)) { - Type *ByValRefType = Arg->hasByValAttr() ? Arg->getParamByValType() - : Arg->getParamByRefType(); - SPIRVType *ElementType = GR->getOrCreateSPIRVType(ByValRefType, MIRBuilder); + if (hasPointeeTypeAttr(Arg)) { + SPIRVType *ElementType = + GR->getOrCreateSPIRVType(getPointeeTypeByAttr(Arg), MIRBuilder); return GR->getOrCreateSPIRVPointerType( ElementType, MIRBuilder, - addressSpaceToStorageClass(getPointerAddressSpace(Arg->getType()), ST)); + addressSpaceToStorageClass(getPointerAddressSpace(ArgType), ST)); } for (auto User : Arg->users()) { diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 5828db6669ff..7c5a38fa48d0 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -14,6 +14,7 @@ #include "SPIRV.h" #include "SPIRVBuiltins.h" #include "SPIRVMetadata.h" +#include "SPIRVSubtarget.h" #include "SPIRVTargetMachine.h" #include "SPIRVUtils.h" #include "llvm/IR/IRBuilder.h" @@ -53,14 +54,22 @@ class SPIRVEmitIntrinsics : public FunctionPass, public InstVisitor { SPIRVTargetMachine *TM = nullptr; + SPIRVGlobalRegistry *GR = nullptr; Function *F = nullptr; bool TrackConstants = true; DenseMap AggrConsts; + DenseMap AggrConstTypes; DenseSet AggrStores; - // deduce values type - DenseMap DeducedElTys; + // deduce element type of untyped pointers Type *deduceElementType(Value *I); + Type *deduceElementTypeHelper(Value *I); + Type *deduceElementTypeHelper(Value *I, std::unordered_set &Visited); + + // deduce nested types of composites + Type *deduceNestedTypeHelper(User *U); + Type *deduceNestedTypeHelper(User *U, Type *Ty, + std::unordered_set &Visited); void preprocessCompositeConstants(IRBuilder<> &B); void preprocessUndefs(IRBuilder<> &B); @@ -92,9 +101,9 @@ class SPIRVEmitIntrinsics void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B); void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B); void processParamTypes(Function *F, IRBuilder<> &B); - Type *deduceFunParamType(Function *F, unsigned OpIdx); - Type *deduceFunParamType(Function *F, unsigned OpIdx, - std::unordered_set &FVisited); + Type *deduceFunParamElementType(Function *F, unsigned OpIdx); + Type *deduceFunParamElementType(Function *F, unsigned OpIdx, + std::unordered_set &FVisited); public: static char ID; @@ -169,17 +178,20 @@ static inline void reportFatalOnTokenType(const Instruction *I) { // Deduce and return a successfully deduced Type of the Instruction, // or nullptr otherwise. -static Type *deduceElementTypeHelper(Value *I, - std::unordered_set &Visited, - DenseMap &DeducedElTys) { +Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I) { + std::unordered_set Visited; + return deduceElementTypeHelper(I, Visited); +} + +Type *SPIRVEmitIntrinsics::deduceElementTypeHelper( + Value *I, std::unordered_set &Visited) { // allow to pass nullptr as an argument if (!I) return nullptr; // maybe already known - auto It = DeducedElTys.find(I); - if (It != DeducedElTys.end()) - return It->second; + if (Type *KnownTy = GR->findDeducedElementType(I)) + return KnownTy; // maybe a cycle if (Visited.find(I) != Visited.end()) @@ -195,25 +207,99 @@ static Type *deduceElementTypeHelper(Value *I, Ty = Ref->getResultElementType(); } else if (auto *Ref = dyn_cast(I)) { Ty = Ref->getValueType(); + if (Value *Op = Ref->getNumOperands() > 0 ? Ref->getOperand(0) : nullptr) { + if (auto *PtrTy = dyn_cast(Ty)) { + if (Type *NestedTy = deduceElementTypeHelper(Op, Visited)) + Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace()); + } else { + Ty = deduceNestedTypeHelper(dyn_cast(Op), Ty, Visited); + } + } } else if (auto *Ref = dyn_cast(I)) { - Ty = deduceElementTypeHelper(Ref->getPointerOperand(), Visited, - DeducedElTys); + Ty = deduceElementTypeHelper(Ref->getPointerOperand(), Visited); } else if (auto *Ref = dyn_cast(I)) { if (Type *Src = Ref->getSrcTy(), *Dest = Ref->getDestTy(); isPointerTy(Src) && isPointerTy(Dest)) - Ty = deduceElementTypeHelper(Ref->getOperand(0), Visited, DeducedElTys); + Ty = deduceElementTypeHelper(Ref->getOperand(0), Visited); } // remember the found relationship - if (Ty) - DeducedElTys[I] = Ty; + if (Ty) { + // specify nested types if needed, otherwise return unchanged + GR->addDeducedElementType(I, Ty); + } return Ty; } -Type *SPIRVEmitIntrinsics::deduceElementType(Value *I) { +// Re-create a type of the value if it has untyped pointer fields, also nested. +// Return the original value type if no corrections of untyped pointer +// information is found or needed. +Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U) { std::unordered_set Visited; - if (Type *Ty = deduceElementTypeHelper(I, Visited, DeducedElTys)) + return deduceNestedTypeHelper(U, U->getType(), Visited); +} + +Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper( + User *U, Type *OrigTy, std::unordered_set &Visited) { + if (!U) + return OrigTy; + + // maybe already known + if (Type *KnownTy = GR->findDeducedCompositeType(U)) + return KnownTy; + + // maybe a cycle + if (Visited.find(U) != Visited.end()) + return OrigTy; + Visited.insert(U); + + if (dyn_cast(OrigTy)) { + SmallVector Tys; + bool Change = false; + for (unsigned i = 0; i < U->getNumOperands(); ++i) { + Value *Op = U->getOperand(i); + Type *OpTy = Op->getType(); + Type *Ty = OpTy; + if (Op) { + if (auto *PtrTy = dyn_cast(OpTy)) { + if (Type *NestedTy = deduceElementTypeHelper(Op, Visited)) + Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace()); + } else { + Ty = deduceNestedTypeHelper(dyn_cast(Op), OpTy, Visited); + } + } + Tys.push_back(Ty); + Change |= Ty != OpTy; + } + if (Change) { + Type *NewTy = StructType::create(Tys); + GR->addDeducedCompositeType(U, NewTy); + return NewTy; + } + } else if (auto *ArrTy = dyn_cast(OrigTy)) { + if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) { + Type *OpTy = ArrTy->getElementType(); + Type *Ty = OpTy; + if (auto *PtrTy = dyn_cast(OpTy)) { + if (Type *NestedTy = deduceElementTypeHelper(Op, Visited)) + Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace()); + } else { + Ty = deduceNestedTypeHelper(dyn_cast(Op), OpTy, Visited); + } + if (Ty != OpTy) { + Type *NewTy = ArrayType::get(Ty, ArrTy->getNumElements()); + GR->addDeducedCompositeType(U, NewTy); + return NewTy; + } + } + } + + return OrigTy; +} + +Type *SPIRVEmitIntrinsics::deduceElementType(Value *I) { + if (Type *Ty = deduceElementTypeHelper(I)) return Ty; return IntegerType::getInt8Ty(I->getContext()); } @@ -257,6 +343,7 @@ void SPIRVEmitIntrinsics::preprocessUndefs(IRBuilder<> &B) { Worklist.push(IntrUndef); I->replaceUsesOfWith(Op, IntrUndef); AggrConsts[IntrUndef] = AggrUndef; + AggrConstTypes[IntrUndef] = AggrUndef->getType(); } } } @@ -282,6 +369,7 @@ void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) { I->replaceUsesOfWith(Op, CCI); KeepInst = true; SEI.AggrConsts[CCI] = AggrC; + SEI.AggrConstTypes[CCI] = SEI.deduceNestedTypeHelper(AggrC); }; if (auto *AggrC = dyn_cast(Op)) { @@ -396,8 +484,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( Pointer = BC->getOperand(0); // Do not emit spv_ptrcast if Pointer's element type is ExpectedElementType - std::unordered_set Visited; - Type *PointerElemTy = deduceElementTypeHelper(Pointer, Visited, DeducedElTys); + Type *PointerElemTy = deduceElementTypeHelper(Pointer); if (PointerElemTy == ExpectedElementType) return; @@ -456,8 +543,8 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( CallInst *CI = buildIntrWithMD( Intrinsic::spv_assign_ptr_type, {Pointer->getType()}, ExpectedElementTypeConst, Pointer, {B.getInt32(AddressSpace)}, B); - DeducedElTys[CI] = ExpectedElementType; - DeducedElTys[Pointer] = ExpectedElementType; + GR->addDeducedElementType(CI, ExpectedElementType); + GR->addDeducedElementType(Pointer, ExpectedElementType); return; } @@ -498,25 +585,29 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, Function *CalledF = CI->getCalledFunction(); SmallVector CalledArgTys; bool HaveTypes = false; - for (auto &CalledArg : CalledF->args()) { - if (!isPointerTy(CalledArg.getType())) { + for (unsigned OpIdx = 0; OpIdx < CalledF->arg_size(); ++OpIdx) { + Argument *CalledArg = CalledF->getArg(OpIdx); + Type *ArgType = CalledArg->getType(); + if (!isPointerTy(ArgType)) { CalledArgTys.push_back(nullptr); - continue; - } - auto It = DeducedElTys.find(&CalledArg); - Type *ParamTy = It != DeducedElTys.end() ? It->second : nullptr; - if (!ParamTy) { - for (User *U : CalledArg.users()) { - if (Instruction *Inst = dyn_cast(U)) { - std::unordered_set Visited; - ParamTy = deduceElementTypeHelper(Inst, Visited, DeducedElTys); - if (ParamTy) - break; + } else if (isTypedPointerTy(ArgType)) { + CalledArgTys.push_back(cast(ArgType)->getElementType()); + HaveTypes = true; + } else { + Type *ElemTy = GR->findDeducedElementType(CalledArg); + if (!ElemTy && hasPointeeTypeAttr(CalledArg)) + ElemTy = getPointeeTypeByAttr(CalledArg); + if (!ElemTy) { + for (User *U : CalledArg->users()) { + if (Instruction *Inst = dyn_cast(U)) { + if ((ElemTy = deduceElementTypeHelper(Inst)) != nullptr) + break; + } } } + HaveTypes |= ElemTy != nullptr; + CalledArgTys.push_back(ElemTy); } - HaveTypes |= ParamTy != nullptr; - CalledArgTys.push_back(ParamTy); } std::string DemangledName = @@ -706,6 +797,10 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV, if (GV.getName() == "llvm.global.annotations") return; if (GV.hasInitializer() && !isa(GV.getInitializer())) { + // Deduce element type and store results in Global Registry. + // Result is ignored, because TypedPointerType is not supported + // by llvm IR general logic. + deduceElementTypeHelper(&GV); Constant *Init = GV.getInitializer(); Type *Ty = isAggrToReplace(Init) ? B.getInt32Ty() : Init->getType(); Constant *Const = isAggrToReplace(Init) ? B.getInt32(1) : Init; @@ -732,7 +827,7 @@ void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I, unsigned AddressSpace = getPointerAddressSpace(I->getType()); CallInst *CI = buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, EltTyConst, I, {B.getInt32(AddressSpace)}, B); - DeducedElTys[CI] = ElemTy; + GR->addDeducedElementType(CI, ElemTy); } void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I, @@ -745,9 +840,10 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I, if (auto *II = dyn_cast(I)) { if (II->getIntrinsicID() == Intrinsic::spv_const_composite || II->getIntrinsicID() == Intrinsic::spv_undef) { - auto t = AggrConsts.find(II); - assert(t != AggrConsts.end()); - TypeToAssign = t->second->getType(); + auto It = AggrConstTypes.find(II); + if (It == AggrConstTypes.end()) + report_fatal_error("Unknown composite intrinsic type"); + TypeToAssign = It->second; } } Constant *Const = UndefValue::get(TypeToAssign); @@ -807,12 +903,13 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I, } } -Type *SPIRVEmitIntrinsics::deduceFunParamType(Function *F, unsigned OpIdx) { +Type *SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F, + unsigned OpIdx) { std::unordered_set FVisited; - return deduceFunParamType(F, OpIdx, FVisited); + return deduceFunParamElementType(F, OpIdx, FVisited); } -Type *SPIRVEmitIntrinsics::deduceFunParamType( +Type *SPIRVEmitIntrinsics::deduceFunParamElementType( Function *F, unsigned OpIdx, std::unordered_set &FVisited) { // maybe a cycle if (FVisited.find(F) != FVisited.end()) @@ -830,15 +927,15 @@ Type *SPIRVEmitIntrinsics::deduceFunParamType( if (!isPointerTy(OpArg->getType())) continue; // maybe we already know operand's element type - if (auto It = DeducedElTys.find(OpArg); It != DeducedElTys.end()) - return It->second; + if (Type *KnownTy = GR->findDeducedElementType(OpArg)) + return KnownTy; // search in actual parameter's users for (User *OpU : OpArg->users()) { Instruction *Inst = dyn_cast(OpU); if (!Inst || Inst == CI) continue; Visited.clear(); - if (Type *Ty = deduceElementTypeHelper(Inst, Visited, DeducedElTys)) + if (Type *Ty = deduceElementTypeHelper(Inst, Visited)) return Ty; } // check if it's a formal parameter of the outer function @@ -857,7 +954,7 @@ Type *SPIRVEmitIntrinsics::deduceFunParamType( // search in function parameters for (auto &Pair : Lookup) { - if (Type *Ty = deduceFunParamType(Pair.first, Pair.second, FVisited)) + if (Type *Ty = deduceFunParamElementType(Pair.first, Pair.second, FVisited)) return Ty; } @@ -866,19 +963,23 @@ Type *SPIRVEmitIntrinsics::deduceFunParamType( void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) { B.SetInsertPointPastAllocas(F); - DenseMap Args; for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) { Argument *Arg = F->getArg(OpIdx); - if (isUntypedPointerTy(Arg->getType()) && - DeducedElTys.find(Arg) == DeducedElTys.end() && - !HasPointeeTypeAttr(Arg)) { - if (Type *ElemTy = deduceFunParamType(F, OpIdx)) { + if (!isUntypedPointerTy(Arg->getType())) + continue; + + Type *ElemTy = GR->findDeducedElementType(Arg); + if (!ElemTy) { + if (hasPointeeTypeAttr(Arg) && + (ElemTy = getPointeeTypeByAttr(Arg)) != nullptr) { + GR->addDeducedElementType(Arg, ElemTy); + } else if ((ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr) { CallInst *AssignPtrTyCI = buildIntrWithMD( Intrinsic::spv_assign_ptr_type, {Arg->getType()}, Constant::getNullValue(ElemTy), Arg, {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B); - DeducedElTys[AssignPtrTyCI] = ElemTy; - DeducedElTys[Arg] = ElemTy; + GR->addDeducedElementType(AssignPtrTyCI, ElemTy); + GR->addDeducedElementType(Arg, ElemTy); } } } @@ -887,9 +988,14 @@ void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) { bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { if (Func.isDeclaration()) return false; + + const SPIRVSubtarget &ST = TM->getSubtarget(Func); + GR = ST.getSPIRVGlobalRegistry(); + F = &Func; IRBuilder<> B(Func.getContext()); AggrConsts.clear(); + AggrConstTypes.clear(); AggrStores.clear(); // StoreInst's operand type can be changed during the next transformations, diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h index ed0f90ff89ce..e0099e529447 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h @@ -41,9 +41,13 @@ class SPIRVGlobalRegistry { // map a Function to its definition (as a machine instruction operand) DenseMap FunctionToInstr; + DenseMap FunctionToInstrRev; // map function pointer (as a machine instruction operand) to the used // Function DenseMap InstrToFunction; + // Maps Functions to their calls (in a form of the machine instruction, + // OpFunctionCall) that happened before the definition is available + DenseMap> ForwardCalls; // Look for an equivalent of the newType in the map. Return the equivalent // if it's found, otherwise insert newType to the map and return the type. @@ -59,6 +63,13 @@ class SPIRVGlobalRegistry { // Holds the maximum ID we have in the module. unsigned Bound; + // Maps values associated with untyped pointers into deduced element types of + // untyped pointers. + DenseMap DeducedElTys; + // Maps composite values to deduced types where untyped pointers are replaced + // with typed ones + DenseMap DeducedNestedTys; + // Add a new OpTypeXXX instruction without checking for duplicates. SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ = @@ -122,6 +133,37 @@ public: void setBound(unsigned V) { Bound = V; } unsigned getBound() { return Bound; } + // Deduced element types of untyped pointers and composites: + // - Add a record to the map of deduced element types. + void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; } + // - Find a record in the map of deduced element types. + Type *findDeducedElementType(const Value *Val) { + auto It = DeducedElTys.find(Val); + return It == DeducedElTys.end() ? nullptr : It->second; + } + // - Add a record to the map of deduced composite types. + void addDeducedCompositeType(Value *Val, Type *Ty) { + DeducedNestedTys[Val] = Ty; + } + // - Find a record in the map of deduced composite types. + Type *findDeducedCompositeType(const Value *Val) { + auto It = DeducedNestedTys.find(Val); + return It == DeducedNestedTys.end() ? nullptr : It->second; + } + // - Find a type of the given Global value + Type *getDeducedGlobalValueType(const GlobalValue *Global) { + // we may know element type if it was deduced earlier + Type *ElementTy = findDeducedElementType(Global); + if (!ElementTy) { + // or we may know element type if it's associated with a composite + // value + if (Value *GlobalElem = + Global->getNumOperands() > 0 ? Global->getOperand(0) : nullptr) + ElementTy = findDeducedCompositeType(GlobalElem); + } + return ElementTy ? ElementTy : Global->getValueType(); + } + // Map a machine operand that represents a use of a function via function // pointer to a machine operand that represents the function definition. // Return either the register or invalid value, because we have no context for @@ -133,18 +175,56 @@ public: auto ResReg = FunctionToInstr.find(ResF->second); return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second; } + + // Map a Function to a machine instruction that represents the function + // definition. + const MachineInstr *getFunctionDefinition(const Function *F) { + if (!F) + return nullptr; + auto MOIt = FunctionToInstr.find(F); + return MOIt == FunctionToInstr.end() ? nullptr : MOIt->second->getParent(); + } + + // Map a Function to a machine instruction that represents the function + // definition. + const Function *getFunctionByDefinition(const MachineInstr *MI) { + if (!MI) + return nullptr; + auto FIt = FunctionToInstrRev.find(MI); + return FIt == FunctionToInstrRev.end() ? nullptr : FIt->second; + } + // map function pointer (as a machine instruction operand) to the used // Function void recordFunctionPointer(const MachineOperand *MO, const Function *F) { InstrToFunction[MO] = F; } + // map a Function to its definition (as a machine instruction) void recordFunctionDefinition(const Function *F, const MachineOperand *MO) { FunctionToInstr[F] = MO; + FunctionToInstrRev[MO->getParent()] = F; } + // Return true if any OpConstantFunctionPointerINTEL were generated bool hasConstFunPtr() { return !InstrToFunction.empty(); } + // Add a record about forward function call. + void addForwardCall(const Function *F, MachineInstr *MI) { + auto It = ForwardCalls.find(F); + if (It == ForwardCalls.end()) + ForwardCalls[F] = {MI}; + else + It->second.push_back(MI); + } + + // Map a Function to the vector of machine instructions that represents + // forward function calls or to nullptr if not found. + SmallVector *getForwardCalls(const Function *F) { + auto It = ForwardCalls.find(F); + return It == ForwardCalls.end() ? nullptr : &It->second; + } + // Get or create a SPIR-V type corresponding the given LLVM IR type, // and map it to the given VReg by creating an ASSIGN_TYPE instruction. SPIRVType *assignTypeToVReg(const Type *Type, Register VReg, diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp index 55b4c47c197d..4f5c1dc4f90b 100644 --- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp @@ -86,8 +86,8 @@ bool SPIRVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, // when there is a type mismatch between results and operand types. static void validatePtrTypes(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, - MachineInstr &I, SPIRVType *ResType, - unsigned OpIdx) { + MachineInstr &I, unsigned OpIdx, + SPIRVType *ResType, const Type *ResTy = nullptr) { Register OpReg = I.getOperand(OpIdx).getReg(); SPIRVType *TypeInst = MRI->getVRegDef(OpReg); SPIRVType *OpType = GR.getSPIRVTypeForVReg( @@ -97,7 +97,13 @@ static void validatePtrTypes(const SPIRVSubtarget &STI, if (!ResType || !OpType || OpType->getOpcode() != SPIRV::OpTypePointer) return; SPIRVType *ElemType = GR.getSPIRVTypeForVReg(OpType->getOperand(2).getReg()); - if (!ElemType || ElemType == ResType) + if (!ElemType) + return; + bool IsSameMF = + ElemType->getParent()->getParent() == ResType->getParent()->getParent(); + bool IsEqualTypes = IsSameMF ? ElemType == ResType + : GR.getTypeForSPIRVType(ElemType) == ResTy; + if (IsEqualTypes) return; // There is a type mismatch between results and operand types // and we insert a bitcast before the instruction to keep SPIR-V code valid @@ -105,7 +111,11 @@ static void validatePtrTypes(const SPIRVSubtarget &STI, static_cast( OpType->getOperand(1).getImm()); MachineIRBuilder MIB(I); - SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(ResType, MIB, SC); + SPIRVType *NewBaseType = + IsSameMF ? ResType + : GR.getOrCreateSPIRVType( + ResTy, MIB, SPIRV::AccessQualifier::ReadWrite, false); + SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(NewBaseType, MIB, SC); if (!GR.isBitcastCompatible(NewPtrType, OpType)) report_fatal_error( "insert validation bitcast: incompatible result and operand types"); @@ -123,6 +133,74 @@ static void validatePtrTypes(const SPIRVSubtarget &STI, I.getOperand(OpIdx).setReg(NewReg); } +// Insert a bitcast before the function call instruction to keep SPIR-V code +// valid when there is a type mismatch between actual and expected types of an +// argument: +// %formal = OpFunctionParameter %formal_type +// ... +// %res = OpFunctionCall %ty %fun %actual ... +// implies that %actual is of %formal_type, and in case of opaque pointers. +// We may need to insert a bitcast to ensure this. +void validateFunCallMachineDef(const SPIRVSubtarget &STI, + MachineRegisterInfo *DefMRI, + MachineRegisterInfo *CallMRI, + SPIRVGlobalRegistry &GR, MachineInstr &FunCall, + MachineInstr *FunDef) { + if (FunDef->getOpcode() != SPIRV::OpFunction) + return; + unsigned OpIdx = 3; + for (FunDef = FunDef->getNextNode(); + FunDef && FunDef->getOpcode() == SPIRV::OpFunctionParameter && + OpIdx < FunCall.getNumOperands(); + FunDef = FunDef->getNextNode(), OpIdx++) { + SPIRVType *DefPtrType = DefMRI->getVRegDef(FunDef->getOperand(1).getReg()); + SPIRVType *DefElemType = + DefPtrType && DefPtrType->getOpcode() == SPIRV::OpTypePointer + ? GR.getSPIRVTypeForVReg(DefPtrType->getOperand(2).getReg()) + : nullptr; + if (DefElemType) { + const Type *DefElemTy = GR.getTypeForSPIRVType(DefElemType); + // Switch GR context to the call site instead of the (default) definition + // side + GR.setCurrentFunc(*FunCall.getParent()->getParent()); + validatePtrTypes(STI, CallMRI, GR, FunCall, OpIdx, DefElemType, + DefElemTy); + GR.setCurrentFunc(*FunDef->getParent()->getParent()); + } + } +} + +// Ensure there is no mismatch between actual and expected arg types: calls +// with a processed definition. Return Function pointer if it's a forward +// call (ahead of definition), and nullptr otherwise. +const Function *validateFunCall(const SPIRVSubtarget &STI, + MachineRegisterInfo *MRI, + SPIRVGlobalRegistry &GR, + MachineInstr &FunCall) { + const GlobalValue *GV = FunCall.getOperand(2).getGlobal(); + const Function *F = dyn_cast(GV); + MachineInstr *FunDef = + const_cast(GR.getFunctionDefinition(F)); + if (!FunDef) + return F; + validateFunCallMachineDef(STI, MRI, MRI, GR, FunCall, FunDef); + return nullptr; +} + +// Ensure there is no mismatch between actual and expected arg types: calls +// ahead of a processed definition. +void validateForwardCalls(const SPIRVSubtarget &STI, + MachineRegisterInfo *DefMRI, SPIRVGlobalRegistry &GR, + MachineInstr &FunDef) { + const Function *F = GR.getFunctionByDefinition(&FunDef); + if (SmallVector *FwdCalls = GR.getForwardCalls(F)) + for (MachineInstr *FunCall : *FwdCalls) { + MachineRegisterInfo *CallMRI = + &FunCall->getParent()->getParent()->getRegInfo(); + validateFunCallMachineDef(STI, DefMRI, CallMRI, GR, *FunCall, &FunDef); + } +} + // TODO: the logic of inserting additional bitcast's is to be moved // to pre-IRTranslation passes eventually void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const { @@ -137,14 +215,28 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const { switch (MI.getOpcode()) { case SPIRV::OpLoad: // OpLoad , ptr %Op implies that %Op is a pointer to - validatePtrTypes(STI, MRI, GR, MI, - GR.getSPIRVTypeForVReg(MI.getOperand(0).getReg()), 2); + validatePtrTypes(STI, MRI, GR, MI, 2, + GR.getSPIRVTypeForVReg(MI.getOperand(0).getReg())); break; case SPIRV::OpStore: // OpStore ptr %Op, implies that %Op points to the 's type - validatePtrTypes(STI, MRI, GR, MI, - GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg()), 0); + validatePtrTypes(STI, MRI, GR, MI, 0, + GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg())); break; + + case SPIRV::OpFunctionCall: + // ensure there is no mismatch between actual and expected arg types: + // calls with a processed definition + if (MI.getNumOperands() > 3) + if (const Function *F = validateFunCall(STI, MRI, GR, MI)) + GR.addForwardCall(F, &MI); + break; + case SPIRV::OpFunction: + // ensure there is no mismatch between actual and expected arg types: + // calls ahead of a processed definition + validateForwardCalls(STI, MRI, GR, MI); + break; + // ensure that LLVM IR bitwise instructions result in logical SPIR-V // instructions when applied to bool type case SPIRV::OpBitwiseOrS: diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 505b19a4d66e..f4525e713c98 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -1897,7 +1897,7 @@ bool SPIRVInstructionSelector::selectGlobalValue( // FIXME: don't use MachineIRBuilder here, replace it with BuildMI. MachineIRBuilder MIRBuilder(I); const GlobalValue *GV = I.getOperand(1).getGlobal(); - Type *GVType = GV->getValueType(); + Type *GVType = GR.getDeducedGlobalValueType(GV); SPIRVType *PointerBaseType; if (GVType->isArrayTy()) { SPIRVType *ArrayElementType = diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp index 41807da6afcb..b133f0ae85de 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -186,8 +186,9 @@ static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, } case TargetOpcode::G_GLOBAL_VALUE: { MIB.setInsertPt(*MI->getParent(), MI); - const auto *Global = MI->getOperand(1).getGlobal(); - auto *Ty = TypedPointerType::get(Global->getValueType(), + const GlobalValue *Global = MI->getOperand(1).getGlobal(); + Type *ElementTy = GR->getDeducedGlobalValueType(Global); + auto *Ty = TypedPointerType::get(ElementTy, Global->getType()->getAddressSpace()); SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB); break; diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index eb87349f0941..c2c3475e1a93 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -127,8 +127,26 @@ inline unsigned getPointerAddressSpace(const Type *T) { } // Return true if the Argument is decorated with a pointee type -inline bool HasPointeeTypeAttr(Argument *Arg) { - return Arg->hasByValAttr() || Arg->hasByRefAttr(); +inline bool hasPointeeTypeAttr(Argument *Arg) { + return Arg->hasByValAttr() || Arg->hasByRefAttr() || Arg->hasStructRetAttr(); +} + +// Return the pointee type of the argument or nullptr otherwise +inline Type *getPointeeTypeByAttr(Argument *Arg) { + if (Arg->hasByValAttr()) + return Arg->getParamByValType(); + if (Arg->hasStructRetAttr()) + return Arg->getParamStructRetType(); + if (Arg->hasByRefAttr()) + return Arg->getParamByRefType(); + return nullptr; +} + +inline Type *reconstructFunctionType(Function *F) { + SmallVector ArgTys; + for (unsigned i = 0; i < F->arg_size(); ++i) + ArgTys.push_back(F->getArg(i)->getType()); + return FunctionType::get(F->getReturnType(), ArgTys, F->isVarArg()); } } // namespace llvm diff --git a/llvm/test/CodeGen/SPIRV/pointers/nested-struct-opaque-pointers.ll b/llvm/test/CodeGen/SPIRV/pointers/nested-struct-opaque-pointers.ll new file mode 100644 index 000000000000..77b895c7762f --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/nested-struct-opaque-pointers.ll @@ -0,0 +1,20 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-NOT: OpTypeInt 8 0 + +@GI = addrspace(1) constant i64 42 + +@GS = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @GI, ptr addrspace(1) @GI } +@GS2 = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @GS, ptr addrspace(1) @GS } +@GS3 = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @GS2, ptr addrspace(1) @GS2 } + +@GPS = addrspace(1) global ptr addrspace(1) @GS3 + +@GPI1 = addrspace(1) global ptr addrspace(1) @GI +@GPI2 = addrspace(1) global ptr addrspace(1) @GPI1 +@GPI3 = addrspace(1) global ptr addrspace(1) @GPI2 + +define spir_kernel void @foo() { + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll b/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll index ce3ab8895a59..6d4913f802c2 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll @@ -1,14 +1,14 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} -; CHECK: %[[TyInt8:.*]] = OpTypeInt 8 0 -; CHECK: %[[TyInt8Ptr:.*]] = OpTypePointer {{[a-zA-Z]+}} %[[TyInt8]] -; CHECK: %[[TyStruct:.*]] = OpTypeStruct %[[TyInt8Ptr]] %[[TyInt8Ptr]] +; CHECK: %[[TyInt64:.*]] = OpTypeInt 64 0 +; CHECK: %[[TyInt64Ptr:.*]] = OpTypePointer {{[a-zA-Z]+}} %[[TyInt64]] +; CHECK: %[[TyStruct:.*]] = OpTypeStruct %[[TyInt64Ptr]] %[[TyInt64Ptr]] ; CHECK: %[[ConstStruct:.*]] = OpConstantComposite %[[TyStruct]] %[[ConstField:.*]] %[[ConstField]] ; CHECK: %[[TyStructPtr:.*]] = OpTypePointer {{[a-zA-Z]+}} %[[TyStruct]] ; CHECK: OpVariable %[[TyStructPtr]] {{[a-zA-Z]+}} %[[ConstStruct]] -@a = addrspace(1) constant i32 123 +@a = addrspace(1) constant i64 42 @struct = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @a, ptr addrspace(1) @a } define spir_kernel void @foo() { diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll index 703f1e22a032..1071d3443056 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll @@ -34,6 +34,12 @@ entry: %addr = addrspacecast ptr addrspace(1) %lptr to ptr addrspace(4) %object = bitcast ptr addrspace(4) %addr to ptr addrspace(4) call spir_func void @foo(ptr addrspace(4) %object, i32 3) + %halfptr = getelementptr inbounds half, ptr addrspace(1) %_arg_cum, i64 1 + %halfaddr = addrspacecast ptr addrspace(1) %halfptr to ptr addrspace(4) + call spir_func void @foo(ptr addrspace(4) %halfaddr, i32 3) + %dblptr = getelementptr inbounds double, ptr addrspace(1) %_arg_cum, i64 1 + %dbladdr = addrspacecast ptr addrspace(1) %dblptr to ptr addrspace(4) + call spir_func void @foo(ptr addrspace(4) %dbladdr, i32 3) ret void } @@ -49,4 +55,3 @@ define void @foo(ptr addrspace(4) noundef %foo_object, i32 noundef %mem_order) { tail call void @foo_stub(ptr addrspace(4) noundef %foo_object, i32 noundef %mem_order) ret void } - -- GitLab From 38f5596feda3276a8aa64fc14e074334017088ca Mon Sep 17 00:00:00 2001 From: Haohai Wen Date: Thu, 28 Mar 2024 15:33:01 +0800 Subject: [PATCH 166/541] [LoopRotate] Add test to track update for inaccurate branch weight (#86495) Branch weight from sample-based PGO may be not inaccurate due to sampling. This test tracks such case where updateBranchWeights wraps unsigned. --- .../LoopRotate/update-branch-weights.ll | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/llvm/test/Transforms/LoopRotate/update-branch-weights.ll b/llvm/test/Transforms/LoopRotate/update-branch-weights.ll index 5d742b64e0ad..acb2038d17bb 100644 --- a/llvm/test/Transforms/LoopRotate/update-branch-weights.ll +++ b/llvm/test/Transforms/LoopRotate/update-branch-weights.ll @@ -232,6 +232,46 @@ loop_exit: ret void } +; BFI_BEFORE-LABEL: block-frequency-info: func6_inaccurate_branch_weight +; BFI_BEFORE: - entry: {{.*}} count = 1024 +; BFI_BEFORE: - loop_header: {{.*}} count = 2047 +; BFI_BEFORE: - loop_body: {{.*}} count = 1023 +; BFI_BEFORE: - loop_exit: {{.*}} count = 1024 + +; BFI_AFTER-LABEL: block-frequency-info: func6_inaccurate_branch_weight +; BFI_AFTER: - entry: {{.*}} count = 1024 +; BFI_AFTER: - loop_body: {{.*}} count = 4294967296 +; BFI_AFTER: - loop_exit: {{.*}} count = 1024 + +; IR-LABEL: define void @func6_inaccurate_branch_weight( +; IR: entry: +; IR: br label %loop_body +; IR: loop_body: +; IR: br i1 %cmp, label %loop_body, label %loop_exit, !prof [[PROF_FUNC6_0:![0-9]+]] +; IR: loop_exit: +; IR: ret void + +; Branch weight from sample-based PGO may be inaccurate due to sampling. +; Count for loop_body in following case should be not less than loop_exit. +; However this may not hold for Sample-based PGO. +define void @func6_inaccurate_branch_weight() !prof !3 { +entry: + br label %loop_header + +loop_header: + %i = phi i32 [0, %entry], [%i_inc, %loop_body] + %cmp = icmp slt i32 %i, 2 + br i1 %cmp, label %loop_body, label %loop_exit, !prof !9 + +loop_body: + store volatile i32 %i, ptr @g, align 4 + %i_inc = add i32 %i, 1 + br label %loop_header + +loop_exit: + ret void +} + !0 = !{!"function_entry_count", i64 1} !1 = !{!"branch_weights", i32 1000, i32 1} !2 = !{!"branch_weights", i32 3000, i32 1000} @@ -241,6 +281,7 @@ loop_exit: !6 = !{!"branch_weights", i32 0, i32 1} !7 = !{!"branch_weights", i32 1, i32 0} !8 = !{!"branch_weights", i32 0, i32 0} +!9 = !{!"branch_weights", i32 1023, i32 1024} ; IR: [[PROF_FUNC0_0]] = !{!"branch_weights", i32 2000, i32 1000} ; IR: [[PROF_FUNC0_1]] = !{!"branch_weights", i32 999, i32 1} @@ -251,3 +292,4 @@ loop_exit: ; IR: [[PROF_FUNC3_0]] = !{!"branch_weights", i32 0, i32 1} ; IR: [[PROF_FUNC4_0]] = !{!"branch_weights", i32 1, i32 0} ; IR: [[PROF_FUNC5_0]] = !{!"branch_weights", i32 0, i32 0} +; IR: [[PROF_FUNC6_0]] = !{!"branch_weights", i32 -1, i32 1024} -- GitLab From 63ea5a4088ff73a47cd3411fad3b42c92a3c64f0 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 28 Mar 2024 09:13:26 +0100 Subject: [PATCH 167/541] [clang] Invalidate the alias template decl if it has multiple written template parameter lists. (#85413) Fixes #85406. - Set the invalid bit for alias template decl where it has multiple written template parameter lists (as the AST node is ill-formed) - don't perform CTAD for invalid alias template decls --- clang/lib/Sema/SemaDeclCXX.cpp | 1 + clang/lib/Sema/SemaTemplate.cpp | 2 ++ clang/test/AST/ast-dump-invalid.cpp | 9 +++++++++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 12 ++++++++++++ 4 files changed, 24 insertions(+) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e9fecaea84b0..f32ff396f8a5 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13589,6 +13589,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, Diag(UsingLoc, diag::err_alias_template_extra_headers) << SourceRange(TemplateParamLists[1]->getTemplateLoc(), TemplateParamLists[TemplateParamLists.size()-1]->getRAngleLoc()); + Invalid = true; } TemplateParameterList *TemplateParams = TemplateParamLists[0]; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index aab72dbaf48c..e575bb2df97f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2731,6 +2731,8 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { // Build deduction guides for a type alias template. void DeclareImplicitDeductionGuidesForTypeAlias( Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) { + if (AliasTemplate->isInvalidDecl()) + return; auto &Context = SemaRef.Context; // FIXME: if there is an explicit deduction guide after the first use of the // type alias usage, we will not cover this explicit deduction guide. fix this diff --git a/clang/test/AST/ast-dump-invalid.cpp b/clang/test/AST/ast-dump-invalid.cpp index 0a301dba51d2..5b6d74194b98 100644 --- a/clang/test/AST/ast-dump-invalid.cpp +++ b/clang/test/AST/ast-dump-invalid.cpp @@ -60,3 +60,12 @@ double Str::foo1(double, invalid_type) // CHECK-NEXT: `-ReturnStmt {{.*}} // CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 45 + +namespace TestAliasTemplateDecl { +template class A; + +template +template using InvalidAlias = A; +// CHECK: TypeAliasTemplateDecl {{.*}} invalid InvalidAlias +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T +} diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 3ce26c8fcd98..ce403285b0f5 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -247,3 +247,15 @@ using Bar = Foo; // expected-note {{could not match 'Foo' Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} } // namespace test18 + +// GH85406, verify no crash on invalid alias templates. +namespace test19 { +template +class Foo {}; + +template +template +using Bar2 = Foo; // expected-error {{extraneous template parameter list in alias template declaration}} + +Bar2 b = 1; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} +} // namespace test19 -- GitLab From 2a2fd488b6bc1f3df7a8c103f53fec8bf849da4a Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Thu, 28 Mar 2024 08:54:27 +0000 Subject: [PATCH 168/541] [RemoveDIs] Update DIBuilder C API and OCaml bindings [2/2] (#86529) Follow on from #84915 which adds the DbgRecord function variants. The C API changes were reviewed in #85657. # C API Update the LLVMDIBuilderInsert... functions to insert DbgRecords instead of debug intrinsics. LLVMDIBuilderInsertDeclareBefore LLVMDIBuilderInsertDeclareAtEnd LLVMDIBuilderInsertDbgValueBefore LLVMDIBuilderInsertDbgValueAtEnd Calling these functions will now cause an assertion if the module is in the wrong debug info format. They should only be used when the module is in "new debug format". Use LLVMIsNewDbgInfoFormat to query and LLVMSetIsNewDbgInfoFormat to change the debug info format of a module. Please see https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-change (RemoveDIsDebugInfo.md) for more info. # OCaml bindings Add set_is_new_dbg_info_format and is_new_dbg_info_format to the OCaml bindings. These can be used to set and query the current debug info mode. These will eventually be removed, but are useful while we're transitioning between old and new debug info formats. Add string_of_lldbgrecord, like string_of_llvalue but prints DbgRecords. In test dbginfo.ml, unconditionally set the module debug info to the new mode and update CHECK lines to check for DbgRecords. Without this change the test crashes because it attempts to insert DbgRecords (new default behaviour of llvm_dibuild_insert_declare_...) into a module that is in the old debug info mode. --- .../ocaml/debuginfo/debuginfo_ocaml.c | 15 ++- .../ocaml/debuginfo/llvm_debuginfo.ml | 10 +- .../ocaml/debuginfo/llvm_debuginfo.mli | 10 +- llvm/bindings/ocaml/llvm/llvm.ml | 2 + llvm/bindings/ocaml/llvm/llvm.mli | 6 + llvm/bindings/ocaml/llvm/llvm_ocaml.c | 9 ++ llvm/bindings/ocaml/llvm/llvm_ocaml.h | 1 + llvm/docs/RemoveDIsDebugInfo.md | 11 +- llvm/include/llvm-c/Core.h | 8 ++ llvm/include/llvm-c/DebugInfo.h | 60 ++++++--- llvm/lib/IR/Core.cpp | 14 ++ llvm/lib/IR/DebugInfo.cpp | 121 ++++++++++++------ llvm/test/Bindings/OCaml/debuginfo.ml | 10 +- llvm/tools/llvm-c-test/debuginfo.c | 13 +- 14 files changed, 212 insertions(+), 78 deletions(-) diff --git a/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c b/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c index a793e893524f..fbe45c0c1e0b 100644 --- a/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c +++ b/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c @@ -972,7 +972,7 @@ value llvm_dibuild_create_parameter_variable_bytecode(value *argv, int arg) { value llvm_dibuild_insert_declare_before_native(value Builder, value Storage, value VarInfo, value Expr, value DebugLoc, value Instr) { - LLVMValueRef Value = LLVMDIBuilderInsertDeclareBefore( + LLVMDbgRecordRef Value = LLVMDIBuilderInsertDeclareBefore( DIBuilder_val(Builder), Value_val(Storage), Metadata_val(VarInfo), Metadata_val(Expr), Metadata_val(DebugLoc), Value_val(Instr)); return to_val(Value); @@ -992,7 +992,7 @@ value llvm_dibuild_insert_declare_before_bytecode(value *argv, int arg) { value llvm_dibuild_insert_declare_at_end_native(value Builder, value Storage, value VarInfo, value Expr, value DebugLoc, value Block) { - LLVMValueRef Value = LLVMDIBuilderInsertDeclareAtEnd( + LLVMDbgRecordRef Value = LLVMDIBuilderInsertDeclareAtEnd( DIBuilder_val(Builder), Value_val(Storage), Metadata_val(VarInfo), Metadata_val(Expr), Metadata_val(DebugLoc), BasicBlock_val(Block)); return to_val(Value); @@ -1012,3 +1012,14 @@ value llvm_dibuild_expression(value Builder, value Addr) { return to_val(LLVMDIBuilderCreateExpression( DIBuilder_val(Builder), (uint64_t *)Op_val(Addr), Wosize_val(Addr))); } + +/* llmodule -> bool */ +value llvm_is_new_dbg_info_format(value Module) { + return Val_bool(LLVMIsNewDbgInfoFormat(Module_val(Module))); +} + +/* llmodule -> bool -> unit */ +value llvm_set_is_new_dbg_info_format(value Module, value UseNewFormat) { + LLVMSetIsNewDbgInfoFormat(Module_val(Module), Bool_val(UseNewFormat)); + return Val_unit; +} diff --git a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml index a6d74ed0eb81..8bb5edb17a2c 100644 --- a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml +++ b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml @@ -599,7 +599,7 @@ external dibuild_insert_declare_before : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> instr:Llvm.llvalue -> - Llvm.llvalue + Llvm.lldbgrecord = "llvm_dibuild_insert_declare_before_bytecode" "llvm_dibuild_insert_declare_before_native" external dibuild_insert_declare_at_end : @@ -609,7 +609,7 @@ external dibuild_insert_declare_at_end : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> block:Llvm.llbasicblock -> - Llvm.llvalue + Llvm.lldbgrecord = "llvm_dibuild_insert_declare_at_end_bytecode" "llvm_dibuild_insert_declare_at_end_native" external dibuild_expression : @@ -617,3 +617,9 @@ external dibuild_expression : Int64.t array -> Llvm.llmetadata = "llvm_dibuild_expression" + +external is_new_dbg_info_format : Llvm.llmodule -> bool + = "llvm_is_new_dbg_info_format" + +external set_is_new_dbg_info_format : Llvm.llmodule -> bool -> unit + = "llvm_set_is_new_dbg_info_format" diff --git a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli index e92778b07589..7c7882ccce85 100644 --- a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli +++ b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli @@ -659,7 +659,7 @@ val dibuild_insert_declare_before : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> instr:Llvm.llvalue -> - Llvm.llvalue + Llvm.lldbgrecord (** [dibuild_insert_declare_before] Insert a new llvm.dbg.declare intrinsic call before the given instruction [instr]. *) @@ -670,7 +670,7 @@ val dibuild_insert_declare_at_end : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> block:Llvm.llbasicblock -> - Llvm.llvalue + Llvm.lldbgrecord (** [dibuild_insert_declare_at_end] Insert a new llvm.dbg.declare intrinsic call at the end of basic block [block]. If [block] has a terminator instruction, the intrinsic is inserted @@ -680,3 +680,9 @@ val dibuild_expression : lldibuilder -> Int64.t array -> Llvm.llmetadata (** [dibuild_expression] Create a new descriptor for the specified variable which has a complex address expression for its address. See LLVMDIBuilderCreateExpression. *) + +val is_new_dbg_info_format : Llvm.llmodule -> bool +(** [is_new_dbg_info_format] See LLVMIsNewDbgInfoFormat *) + +val set_is_new_dbg_info_format : Llvm.llmodule -> bool -> unit +(** [set_is_new_dbg_info_format] See LLVMSetIsNewDbgInfoFormat *) diff --git a/llvm/bindings/ocaml/llvm/llvm.ml b/llvm/bindings/ocaml/llvm/llvm.ml index 057798fc0cea..003fd750cd9f 100644 --- a/llvm/bindings/ocaml/llvm/llvm.ml +++ b/llvm/bindings/ocaml/llvm/llvm.ml @@ -12,6 +12,7 @@ type llmodule type llmetadata type lltype type llvalue +type lldbgrecord type lluse type llbasicblock type llbuilder @@ -528,6 +529,7 @@ external value_name : llvalue -> string = "llvm_value_name" external set_value_name : string -> llvalue -> unit = "llvm_set_value_name" external dump_value : llvalue -> unit = "llvm_dump_value" external string_of_llvalue : llvalue -> string = "llvm_string_of_llvalue" +external string_of_lldbgrecord : lldbgrecord -> string = "llvm_string_of_lldbgrecord" external replace_all_uses_with : llvalue -> llvalue -> unit = "llvm_replace_all_uses_with" diff --git a/llvm/bindings/ocaml/llvm/llvm.mli b/llvm/bindings/ocaml/llvm/llvm.mli index e0febb79a2b6..93540c619efb 100644 --- a/llvm/bindings/ocaml/llvm/llvm.mli +++ b/llvm/bindings/ocaml/llvm/llvm.mli @@ -36,6 +36,9 @@ type lltype This type covers a wide range of subclasses. *) type llvalue +(** Non-instruction debug info record. See the [llvm::DbgRecord] class.*) +type lldbgrecord + (** Used to store users and usees of values. See the [llvm::Use] class. *) type lluse @@ -793,6 +796,9 @@ val dump_value : llvalue -> unit (** [string_of_llvalue v] returns a string describing the value [v]. *) val string_of_llvalue : llvalue -> string +(** [string_of_lldbgrecord r] returns a string describing the DbgRecord [r]. *) +val string_of_lldbgrecord : lldbgrecord -> string + (** [replace_all_uses_with old new] replaces all uses of the value [old] with the value [new]. See the method [llvm::Value::replaceAllUsesWith]. *) val replace_all_uses_with : llvalue -> llvalue -> unit diff --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.c b/llvm/bindings/ocaml/llvm/llvm_ocaml.c index 55679f218b30..6d08d78b8445 100644 --- a/llvm/bindings/ocaml/llvm/llvm_ocaml.c +++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.c @@ -800,6 +800,15 @@ value llvm_string_of_llvalue(value M) { return ValueStr; } +/* lldbgrecord -> string */ +value llvm_string_of_lldbgrecord(value Record) { + char *ValueCStr = LLVMPrintDbgRecordToString(DbgRecord_val(Record)); + value ValueStr = caml_copy_string(ValueCStr); + LLVMDisposeMessage(ValueCStr); + + return ValueStr; +} + /* llvalue -> llvalue -> unit */ value llvm_replace_all_uses_with(value OldVal, value NewVal) { LLVMReplaceAllUsesWith(Value_val(OldVal), Value_val(NewVal)); diff --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.h b/llvm/bindings/ocaml/llvm/llvm_ocaml.h index a3791744e647..ec60d6a5dad6 100644 --- a/llvm/bindings/ocaml/llvm/llvm_ocaml.h +++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.h @@ -53,6 +53,7 @@ void *from_val_array(value Elements); #define Metadata_val(v) ((LLVMMetadataRef)from_val(v)) #define Type_val(v) ((LLVMTypeRef)from_val(v)) #define Value_val(v) ((LLVMValueRef)from_val(v)) +#define DbgRecord_val(v) ((LLVMDbgRecordRef)from_val(v)) #define Use_val(v) ((LLVMUseRef)from_val(v)) #define BasicBlock_val(v) ((LLVMBasicBlockRef)from_val(v)) #define MemoryBuffer_val(v) ((LLVMMemoryBufferRef)from_val(v)) diff --git a/llvm/docs/RemoveDIsDebugInfo.md b/llvm/docs/RemoveDIsDebugInfo.md index a2f1e173d9d9..9e50a2a604aa 100644 --- a/llvm/docs/RemoveDIsDebugInfo.md +++ b/llvm/docs/RemoveDIsDebugInfo.md @@ -40,15 +40,22 @@ New functions (all to be deprecated) LLVMIsNewDbgInfoFormat # Returns true if the module is in the new non-instruction mode. LLVMSetIsNewDbgInfoFormat # Convert to the requested debug info format. -LLVMDIBuilderInsertDeclareIntrinsicBefore # Insert a debug intrinsic (old debug info format). +LLVMDIBuilderInsertDeclareIntrinsicBefore # Insert a debug intrinsic (old debug info format). LLVMDIBuilderInsertDeclareIntrinsicAtEnd # Same as above. LLVMDIBuilderInsertDbgValueIntrinsicBefore # Same as above. LLVMDIBuilderInsertDbgValueIntrinsicAtEnd # Same as above. -LLVMDIBuilderInsertDeclareRecordBefore # Insert a debug record (new debug info format). +LLVMDIBuilderInsertDeclareRecordBefore # Insert a debug record (new debug info format). LLVMDIBuilderInsertDeclareRecordAtEnd # Same as above. LLVMDIBuilderInsertDbgValueRecordBefore # Same as above. LLVMDIBuilderInsertDbgValueRecordAtEnd # Same as above. + +Existing functions (behaviour change) +------------------------------------- +LLVMDIBuilderInsertDeclareBefore # Insert a debug record (new debug info format) instead of a debug intrinsic (old debug info format). +LLVMDIBuilderInsertDeclareAtEnd # Same as above. +LLVMDIBuilderInsertDbgValueBefore # Same as above. +LLVMDIBuilderInsertDbgValueAtEnd # Same as above. ``` # Anything else? diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 254c298abe4b..6be5957ce610 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -1866,6 +1866,14 @@ void LLVMDumpValue(LLVMValueRef Val); */ char *LLVMPrintValueToString(LLVMValueRef Val); +/** + * Return a string representation of the DbgRecord. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::DbgRecord::print() + */ +char *LLVMPrintDbgRecordToString(LLVMDbgRecordRef Record); + /** * Replace all uses of a value with another one. * diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h index b23ff63c862f..dab1d697761b 100644 --- a/llvm/include/llvm-c/DebugInfo.h +++ b/llvm/include/llvm-c/DebugInfo.h @@ -1249,7 +1249,12 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( LLVMMetadataRef Decl, uint32_t AlignInBits); /* - * Insert a new llvm.dbg.declare intrinsic call before the given instruction. + * Insert a new Declare DbgRecord before the given instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * \param Builder The DIBuilder. * \param Storage The storage of the variable to declare. * \param VarInfo The variable's debug info descriptor. @@ -1257,13 +1262,13 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( * \param DebugLoc Debug info location. * \param Instr Instruction acting as a location for the new intrinsic. */ -LLVMValueRef +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** * Soon to be deprecated. - * Only use in "old debug mode" (LLVMIsNewDbgFormat() is false). + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a new llvm.dbg.declare intrinsic call before the given instruction. @@ -1279,7 +1284,7 @@ LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicBefore( LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** * Soon to be deprecated. - * Only use in "new debug mode" (LLVMIsNewDbgFormat() is true). + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a Declare DbgRecord before the given instruction. @@ -1295,9 +1300,14 @@ LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordBefore( LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** - * Insert a new llvm.dbg.declare intrinsic call at the end of the given basic - * block. If the basic block has a terminator instruction, the intrinsic is - * inserted before that terminator instruction. + * Insert a new Declare DbgRecord at the end of the given basic block. If the + * basic block has a terminator instruction, the intrinsic is inserted before + * that terminator instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * \param Builder The DIBuilder. * \param Storage The storage of the variable to declare. * \param VarInfo The variable's debug info descriptor. @@ -1305,12 +1315,12 @@ LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordBefore( * \param DebugLoc Debug info location. * \param Block Basic block acting as a location for the new intrinsic. */ -LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); /** * Soon to be deprecated. - * Only use in "old debug mode" (LLVMIsNewDbgFormat() is false). + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a new llvm.dbg.declare intrinsic call at the end of the given basic @@ -1328,7 +1338,7 @@ LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicAtEnd( LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); /** * Soon to be deprecated. - * Only use in "new debug mode" (LLVMIsNewDbgFormat() is true). + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a Declare DbgRecord at the end of the given basic block. If the basic @@ -1346,7 +1356,12 @@ LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordAtEnd( LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); /** - * Insert a new llvm.dbg.value intrinsic call before the given instruction. + * Insert a new Value DbgRecord before the given instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * \param Builder The DIBuilder. * \param Val The value of the variable. * \param VarInfo The variable's debug info descriptor. @@ -1354,13 +1369,13 @@ LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordAtEnd( * \param DebugLoc Debug info location. * \param Instr Instruction acting as a location for the new intrinsic. */ -LLVMValueRef +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** * Soon to be deprecated. - * Only use in "old debug mode" (Module::IsNewDbgInfoFormat is false). + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a new llvm.dbg.value intrinsic call before the given instruction. @@ -1376,7 +1391,7 @@ LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicBefore( LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** * Soon to be deprecated. - * Only use in "new debug mode" (Module::IsNewDbgInfoFormat is true). + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a new llvm.dbg.value intrinsic call before the given instruction. @@ -1392,9 +1407,14 @@ LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordBefore( LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** - * Insert a new llvm.dbg.value intrinsic call at the end of the given basic - * block. If the basic block has a terminator instruction, the intrinsic is - * inserted before that terminator instruction. + * Insert a new Value DbgRecord at the end of the given basic block. If the + * basic block has a terminator instruction, the intrinsic is inserted before + * that terminator instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * \param Builder The DIBuilder. * \param Val The value of the variable. * \param VarInfo The variable's debug info descriptor. @@ -1402,12 +1422,12 @@ LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordBefore( * \param DebugLoc Debug info location. * \param Block Basic block acting as a location for the new intrinsic. */ -LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd( +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); /** * Soon to be deprecated. - * Only use in "old debug mode" (Module::IsNewDbgInfoFormat is false). + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a new llvm.dbg.value intrinsic call at the end of the given basic @@ -1425,7 +1445,7 @@ LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicAtEnd( LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); /** * Soon to be deprecated. - * Only use in "new debug mode" (Module::IsNewDbgInfoFormat is true). + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes * * Insert a new llvm.dbg.value intrinsic call at the end of the given basic diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 3aee61957252..8ce9c5ca63be 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -990,6 +990,20 @@ char* LLVMPrintValueToString(LLVMValueRef Val) { return strdup(buf.c_str()); } +char *LLVMPrintDbgRecordToString(LLVMDbgRecordRef Record) { + std::string buf; + raw_string_ostream os(buf); + + if (unwrap(Record)) + unwrap(Record)->print(os); + else + os << "Printing DbgRecord"; + + os.flush(); + + return strdup(buf.c_str()); +} + void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) { unwrap(OldVal)->replaceAllUsesWith(unwrap(NewVal)); } diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 09bce9df1f33..4206162d1768 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1665,12 +1665,12 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( unwrapDI(Decl), nullptr, AlignInBits)); } -LLVMValueRef +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { - return LLVMDIBuilderInsertDeclareIntrinsicBefore(Builder, Storage, VarInfo, - Expr, DL, Instr); + return LLVMDIBuilderInsertDeclareRecordBefore(Builder, Storage, VarInfo, Expr, + DL, Instr); } LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicBefore( LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, @@ -1679,27 +1679,38 @@ LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicBefore( unwrap(Storage), unwrap(VarInfo), unwrap(Expr), unwrap(DL), unwrap(Instr)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast(DbgInst)); } LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordBefore( LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { - return wrap( - unwrap(Builder) - ->insertDeclare(unwrap(Storage), unwrap(VarInfo), - unwrap(Expr), unwrap(DL), - unwrap(Instr)) - .get()); + DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( + unwrap(Storage), unwrap(VarInfo), + unwrap(Expr), unwrap(DL), + unwrap(Instr)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast(DbgInst)); } -LLVMValueRef +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { - return LLVMDIBuilderInsertDeclareIntrinsicAtEnd(Builder, Storage, VarInfo, - Expr, DL, Block); + return LLVMDIBuilderInsertDeclareRecordAtEnd(Builder, Storage, VarInfo, Expr, + DL, Block); } LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, @@ -1707,26 +1718,36 @@ LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicAtEnd( DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( unwrap(Storage), unwrap(VarInfo), unwrap(Expr), unwrap(DL), unwrap(Block)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast(DbgInst)); } LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { - return wrap(unwrap(Builder) - ->insertDeclare(unwrap(Storage), - unwrap(VarInfo), - unwrap(Expr), - unwrap(DL), unwrap(Block)) - .get()); + DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( + unwrap(Storage), unwrap(VarInfo), + unwrap(Expr), unwrap(DL), unwrap(Block)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast(DbgInst)); } -LLVMValueRef LLVMDIBuilderInsertDbgValueBefore( +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueBefore( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { - return LLVMDIBuilderInsertDbgValueIntrinsicBefore(Builder, Val, VarInfo, Expr, - DebugLoc, Instr); + return LLVMDIBuilderInsertDbgValueRecordBefore(Builder, Val, VarInfo, Expr, + DebugLoc, Instr); } LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicBefore( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, @@ -1734,26 +1755,36 @@ LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicBefore( DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( unwrap(Val), unwrap(VarInfo), unwrap(Expr), unwrap(DebugLoc), unwrap(Instr)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast(DbgInst)); } LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordBefore( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { - return wrap(unwrap(Builder) - ->insertDbgValueIntrinsic( - unwrap(Val), unwrap(VarInfo), - unwrap(Expr), unwrap(DebugLoc), - unwrap(Instr)) - .get()); + DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( + unwrap(Val), unwrap(VarInfo), unwrap(Expr), + unwrap(DebugLoc), unwrap(Instr)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast(DbgInst)); } -LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd( +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { - return LLVMDIBuilderInsertDbgValueIntrinsicAtEnd(Builder, Val, VarInfo, Expr, - DebugLoc, Block); + return LLVMDIBuilderInsertDbgValueRecordAtEnd(Builder, Val, VarInfo, Expr, + DebugLoc, Block); } LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, @@ -1761,19 +1792,29 @@ LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicAtEnd( DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( unwrap(Val), unwrap(VarInfo), unwrap(Expr), unwrap(DebugLoc), unwrap(Block)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast(DbgInst)); } LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { - return wrap(unwrap(Builder) - ->insertDbgValueIntrinsic( - unwrap(Val), unwrap(VarInfo), - unwrap(Expr), unwrap(DebugLoc), - unwrap(Block)) - .get()); + DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( + unwrap(Val), unwrap(VarInfo), unwrap(Expr), + unwrap(DebugLoc), unwrap(Block)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast(DbgInst)); } LLVMMetadataRef LLVMDIBuilderCreateAutoVariable( diff --git a/llvm/test/Bindings/OCaml/debuginfo.ml b/llvm/test/Bindings/OCaml/debuginfo.ml index d469d4715b00..f95800dfcb02 100644 --- a/llvm/test/Bindings/OCaml/debuginfo.ml +++ b/llvm/test/Bindings/OCaml/debuginfo.ml @@ -39,6 +39,8 @@ let prepare_target llmod = let new_module () = let m = Llvm.create_module context module_name in let () = prepare_target m in + let () = Llvm_debuginfo.set_is_new_dbg_info_format m true in + insist (Llvm_debuginfo.is_new_dbg_info_format m); m let test_get_module () = @@ -285,8 +287,8 @@ let test_variables f dibuilder file_di fun_di = ~var_info:auto_var ~expr:(Llvm_debuginfo.dibuild_expression dibuilder [||]) ~location ~instr:entry_term in - let () = Printf.printf "%s\n" (Llvm.string_of_llvalue vdi) in - (* CHECK: call void @llvm.dbg.declare(metadata ptr %my_alloca, metadata {{![0-9]+}}, metadata !DIExpression()), !dbg {{\![0-9]+}} + let () = Printf.printf "%s\n" (Llvm.string_of_lldbgrecord vdi) in + (* CHECK: dbg_declare(ptr %my_alloca, ![[#]], !DIExpression(), ![[#]]) *) let arg0 = (Llvm.params f).(0) in let arg_var = Llvm_debuginfo.dibuild_create_parameter_variable dibuilder ~scope:fun_di @@ -297,8 +299,8 @@ let test_variables f dibuilder file_di fun_di = ~var_info:arg_var ~expr:(Llvm_debuginfo.dibuild_expression dibuilder [||]) ~location ~instr:entry_term in - let () = Printf.printf "%s\n" (Llvm.string_of_llvalue argdi) in - (* CHECK: call void @llvm.dbg.declare(metadata i32 %0, metadata {{![0-9]+}}, metadata !DIExpression()), !dbg {{\![0-9]+}} + let () = Printf.printf "%s\n" (Llvm.string_of_lldbgrecord argdi) in + (* CHECK: dbg_declare(i32 %0, ![[#]], !DIExpression(), ![[#]]) *) () diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index 78ccaf12a380..9b5c37b05d90 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -136,12 +136,13 @@ int llvm_test_dibuilder(bool NewDebugInfoFormat) { LLVMMetadataRef FooParamVar1 = LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "a", 1, 1, File, 42, Int64Ty, true, 0); + if (LLVMIsNewDbgInfoFormat(M)) - LLVMDIBuilderInsertDeclareRecordAtEnd( + LLVMDIBuilderInsertDeclareAtEnd( DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, FooParamExpression, FooParamLocation, FooEntryBlock); else - LLVMDIBuilderInsertDeclareAtEnd( + LLVMDIBuilderInsertDeclareIntrinsicAtEnd( DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, FooParamExpression, FooParamLocation, FooEntryBlock); LLVMMetadataRef FooParamVar2 = @@ -149,11 +150,11 @@ int llvm_test_dibuilder(bool NewDebugInfoFormat) { 42, Int64Ty, true, 0); if (LLVMIsNewDbgInfoFormat(M)) - LLVMDIBuilderInsertDeclareRecordAtEnd( + LLVMDIBuilderInsertDeclareAtEnd( DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, FooParamExpression, FooParamLocation, FooEntryBlock); else - LLVMDIBuilderInsertDeclareAtEnd( + LLVMDIBuilderInsertDeclareIntrinsicAtEnd( DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, FooParamExpression, FooParamLocation, FooEntryBlock); @@ -161,11 +162,11 @@ int llvm_test_dibuilder(bool NewDebugInfoFormat) { LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "c", 1, 3, File, 42, VectorTy, true, 0); if (LLVMIsNewDbgInfoFormat(M)) - LLVMDIBuilderInsertDeclareRecordAtEnd( + LLVMDIBuilderInsertDeclareAtEnd( DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, FooParamExpression, FooParamLocation, FooEntryBlock); else - LLVMDIBuilderInsertDeclareAtEnd( + LLVMDIBuilderInsertDeclareIntrinsicAtEnd( DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, FooParamExpression, FooParamLocation, FooEntryBlock); -- GitLab From 88b10f3e3aa93232f1f530cf8dfe1227f5f74ae9 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 28 Mar 2024 08:57:27 +0000 Subject: [PATCH 169/541] [MC][AArch64] Segregate constant pool caches by size. (#86832) If you write a 32- and a 64-bit LDR instruction that both refer to the same constant or symbol using the = syntax: ``` ldr w0, =something ldr x1, =something ``` then the first call to `ConstantPool::addEntry` will insert the constant into its cache of existing entries, and the second one will find the cache entry and reuse it. This results in a 64-bit load from a 32-bit constant, reading nonsense into the other half of the target register. In this patch I've done the simplest fix: include the size of the constant pool entry as part of the key used to index the cache. So now 32- and 64-bit constant loads will never share a constant pool entry. There's scope for doing this better, in principle: you could imagine merging the two slots with appropriate overlap, so that the 32-bit load loads the LSW of the 64-bit value. But that's much more complicated: you have to take endianness into account, and maybe also adjust the size of an existing entry. This is the simplest fix that restores correctness. --- llvm/include/llvm/MC/ConstantPools.h | 9 ++++++-- llvm/lib/MC/ConstantPools.cpp | 9 ++++---- llvm/test/MC/AArch64/constant-pool-sizes.s | 25 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 llvm/test/MC/AArch64/constant-pool-sizes.s diff --git a/llvm/include/llvm/MC/ConstantPools.h b/llvm/include/llvm/MC/ConstantPools.h index 7eac75362eff..ff21ccda07a8 100644 --- a/llvm/include/llvm/MC/ConstantPools.h +++ b/llvm/include/llvm/MC/ConstantPools.h @@ -43,8 +43,13 @@ struct ConstantPoolEntry { class ConstantPool { using EntryVecTy = SmallVector; EntryVecTy Entries; - std::map CachedConstantEntries; - DenseMap CachedSymbolEntries; + + // Caches of entries that already exist, indexed by their contents + // and also the size of the constant. + std::map, const MCSymbolRefExpr *> + CachedConstantEntries; + DenseMap, const MCSymbolRefExpr *> + CachedSymbolEntries; public: // Initialize a new empty constant pool diff --git a/llvm/lib/MC/ConstantPools.cpp b/llvm/lib/MC/ConstantPools.cpp index f895cc6413d7..824d2463f30f 100644 --- a/llvm/lib/MC/ConstantPools.cpp +++ b/llvm/lib/MC/ConstantPools.cpp @@ -43,14 +43,15 @@ const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context, // Check if there is existing entry for the same constant. If so, reuse it. if (C) { - auto CItr = CachedConstantEntries.find(C->getValue()); + auto CItr = CachedConstantEntries.find(std::make_pair(C->getValue(), Size)); if (CItr != CachedConstantEntries.end()) return CItr->second; } // Check if there is existing entry for the same symbol. If so, reuse it. if (S) { - auto SItr = CachedSymbolEntries.find(&(S->getSymbol())); + auto SItr = + CachedSymbolEntries.find(std::make_pair(&(S->getSymbol()), Size)); if (SItr != CachedSymbolEntries.end()) return SItr->second; } @@ -60,9 +61,9 @@ const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context, Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc)); const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context); if (C) - CachedConstantEntries[C->getValue()] = SymRef; + CachedConstantEntries[std::make_pair(C->getValue(), Size)] = SymRef; if (S) - CachedSymbolEntries[&(S->getSymbol())] = SymRef; + CachedSymbolEntries[std::make_pair(&(S->getSymbol()), Size)] = SymRef; return SymRef; } diff --git a/llvm/test/MC/AArch64/constant-pool-sizes.s b/llvm/test/MC/AArch64/constant-pool-sizes.s new file mode 100644 index 000000000000..279402af025f --- /dev/null +++ b/llvm/test/MC/AArch64/constant-pool-sizes.s @@ -0,0 +1,25 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu %s | FileCheck %s + + ldr w0, =symbol + ldr x1, =symbol + + ldr w2, =1234567890 + ldr x3, =1234567890 + +// CHECK: ldr w0, .Ltmp0 +// CHECK: ldr x1, .Ltmp1 +// CHECK: ldr w2, .Ltmp2 +// CHECK: ldr x3, .Ltmp3 + +// CHECK: .p2align 2, 0x0 +// CHECK-NEXT:.Ltmp0: +// CHECK-NEXT: .word symbol +// CHECK: .p2align 3, 0x0 +// CHECK-NEXT:.Ltmp1: +// CHECK-NEXT: .xword symbol +// CHECK: .p2align 2, 0x0 +// CHECK-NEXT:.Ltmp2: +// CHECK-NEXT: .word 1234567890 +// CHECK: .p2align 3, 0x0 +// CHECK-NEXT:.Ltmp3: +// CHECK-NEXT: .xword 1234567890 -- GitLab From eff4593a642692deb2b76d9d144ad5611bb69e08 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Thu, 28 Mar 2024 16:56:13 +0800 Subject: [PATCH 170/541] [RISCV] Add test case for missed vwaddu.vv due to add->or combine. NFC We should be able to recover this with combineBinOp_VLToVWBinOp_VL if we check that the or has the disjoint flag set. --- llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll index 0a7051633a19..36bc10f055b8 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll @@ -1392,3 +1392,25 @@ define @i1_zext( %va, %vb store i9 42, ptr %p ret %vd } + +; %x.i32 and %y.i32 are disjoint, so DAGCombiner will combine it into an or. +; FIXME: We should be able to recover the or into vwaddu.vv if the disjoint +; flag is set. +define @disjoint_or( %x.i8, %y.i8) { +; CHECK-LABEL: disjoint_or: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vi v8, v10, 8 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf4 v8, v9 +; CHECK-NEXT: vor.vv v8, v10, v8 +; CHECK-NEXT: ret + %x.i16 = zext %x.i8 to + %x.shl = shl %x.i16, shufflevector( insertelement( poison, i16 8, i32 0), poison, zeroinitializer) + %x.i32 = zext %x.shl to + %y.i32 = zext %y.i8 to + %add = add %x.i32, %y.i32 + ret %add +} -- GitLab From 8d77d362af6ade32f087c051fe4774a3891f6ec9 Mon Sep 17 00:00:00 2001 From: martinboehme Date: Thu, 28 Mar 2024 10:12:45 +0100 Subject: [PATCH 171/541] [clang][dataflow] Introduce a helper class for handling record initializer lists. (#86675) This is currently only used in one place, but I'm working on a patch that will use this from a second place. And I think this already improves the readability of the one place this is used so far. --- .../FlowSensitive/DataflowEnvironment.h | 29 +++++++++ .../FlowSensitive/DataflowEnvironment.cpp | 36 +++++++++++ clang/lib/Analysis/FlowSensitive/Transfer.cpp | 61 +++++-------------- 3 files changed, 81 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index 2330697299fd..c30bccd06674 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -744,6 +744,35 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, std::vector getFieldsForInitListExpr(const InitListExpr *InitList); +/// Helper class for initialization of a record with an `InitListExpr`. +/// `InitListExpr::inits()` contains the initializers for both the base classes +/// and the fields of the record; this helper class separates these out into two +/// different lists. In addition, it deals with special cases associated with +/// unions. +class RecordInitListHelper { +public: + // `InitList` must have record type. + RecordInitListHelper(const InitListExpr *InitList); + + // Base classes with their associated initializer expressions. + ArrayRef> base_inits() const { + return BaseInits; + } + + // Fields with their associated initializer expressions. + ArrayRef> field_inits() const { + return FieldInits; + } + +private: + SmallVector> BaseInits; + SmallVector> FieldInits; + + // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a + // member variable because we store a pointer to it in `FieldInits`. + std::optional ImplicitValueInitForUnion; +}; + /// Associates a new `RecordValue` with `Loc` and returns the new value. RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env); diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 70e0623805a8..f729d676dd0d 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -1169,6 +1169,42 @@ getFieldsForInitListExpr(const InitListExpr *InitList) { return Fields; } +RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList) { + auto *RD = InitList->getType()->getAsCXXRecordDecl(); + assert(RD != nullptr); + + std::vector Fields = getFieldsForInitListExpr(InitList); + ArrayRef Inits = InitList->inits(); + + // Unions initialized with an empty initializer list need special treatment. + // For structs/classes initialized with an empty initializer list, Clang + // puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions, + // it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves. + SmallVector InitsForUnion; + if (InitList->getType()->isUnionType() && Inits.empty()) { + assert(Fields.size() == 1); + ImplicitValueInitForUnion.emplace(Fields.front()->getType()); + InitsForUnion.push_back(&*ImplicitValueInitForUnion); + Inits = InitsForUnion; + } + + size_t InitIdx = 0; + + assert(Fields.size() + RD->getNumBases() == Inits.size()); + for (const CXXBaseSpecifier &Base : RD->bases()) { + assert(InitIdx < Inits.size()); + Expr *Init = Inits[InitIdx++]; + BaseInits.emplace_back(&Base, Init); + } + + assert(Fields.size() == Inits.size() - InitIdx); + for (const FieldDecl *Field : Fields) { + assert(InitIdx < Inits.size()); + Expr *Init = Inits[InitIdx++]; + FieldInits.emplace_back(Field, Init); + } +} + RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) { auto &NewVal = Env.create(Loc); Env.setValue(Loc, NewVal); diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 960e9688ffb7..0a2e8368d541 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -689,51 +689,22 @@ public: } llvm::DenseMap FieldLocs; - - // This only contains the direct fields for the given type. - std::vector FieldsForInit = getFieldsForInitListExpr(S); - - // `S->inits()` contains all the initializer expressions, including the - // ones for direct base classes. - ArrayRef Inits = S->inits(); - size_t InitIdx = 0; - - // Unions initialized with an empty initializer list need special treatment. - // For structs/classes initialized with an empty initializer list, Clang - // puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions, - // it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves. - std::optional ImplicitValueInitForUnion; - SmallVector InitsForUnion; - if (S->getType()->isUnionType() && Inits.empty()) { - assert(FieldsForInit.size() == 1); - ImplicitValueInitForUnion.emplace(FieldsForInit.front()->getType()); - InitsForUnion.push_back(&*ImplicitValueInitForUnion); - Inits = InitsForUnion; - } - - // Initialize base classes. - if (auto* R = S->getType()->getAsCXXRecordDecl()) { - assert(FieldsForInit.size() + R->getNumBases() == Inits.size()); - for ([[maybe_unused]] const CXXBaseSpecifier &Base : R->bases()) { - assert(InitIdx < Inits.size()); - auto Init = Inits[InitIdx++]; - assert(Base.getType().getCanonicalType() == - Init->getType().getCanonicalType()); - auto *BaseVal = Env.get(*Init); - if (!BaseVal) - BaseVal = cast(Env.createValue(Init->getType())); - // Take ownership of the fields of the `RecordValue` for the base class - // and incorporate them into the "flattened" set of fields for the - // derived class. - auto Children = BaseVal->getLoc().children(); - FieldLocs.insert(Children.begin(), Children.end()); - } - } - - assert(FieldsForInit.size() == Inits.size() - InitIdx); - for (auto Field : FieldsForInit) { - assert(InitIdx < Inits.size()); - auto Init = Inits[InitIdx++]; + RecordInitListHelper InitListHelper(S); + + for (auto [Base, Init] : InitListHelper.base_inits()) { + assert(Base->getType().getCanonicalType() == + Init->getType().getCanonicalType()); + auto *BaseVal = Env.get(*Init); + if (!BaseVal) + BaseVal = cast(Env.createValue(Init->getType())); + // Take ownership of the fields of the `RecordValue` for the base class + // and incorporate them into the "flattened" set of fields for the + // derived class. + auto Children = BaseVal->getLoc().children(); + FieldLocs.insert(Children.begin(), Children.end()); + } + + for (auto [Field, Init] : InitListHelper.field_inits()) { assert( // The types are same, or Field->getType().getCanonicalType().getUnqualifiedType() == -- GitLab From 912e2c47589d7f4de3e59e99920fe9a60281db2a Mon Sep 17 00:00:00 2001 From: Shan Huang <52285902006@stu.ecnu.edu.cn> Date: Thu, 28 Mar 2024 17:37:33 +0800 Subject: [PATCH 172/541] [Debuginfo][TailCallElim] Fix #86262: drop the debug location of entry branch (#86269) This pr fixes #86262. --------- Co-authored-by: Stephen Tozer --- llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp | 4 +++- llvm/test/Transforms/TailCallElim/debugloc.ll | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index 519ff3221a3b..34d39f3fe6dc 100644 --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -510,7 +510,9 @@ void TailRecursionEliminator::createTailRecurseLoopHeader(CallInst *CI) { NewEntry->takeName(HeaderBB); HeaderBB->setName("tailrecurse"); BranchInst *BI = BranchInst::Create(HeaderBB, NewEntry); - BI->setDebugLoc(CI->getDebugLoc()); + // If the new branch preserves the debug location of CI, it could result in + // misleading stepping, if CI is located in a conditional branch. + // So, here we don't give any debug location to BI. // Move all fixed sized allocas from HeaderBB to NewEntry. for (BasicBlock::iterator OEBI = HeaderBB->begin(), E = HeaderBB->end(), diff --git a/llvm/test/Transforms/TailCallElim/debugloc.ll b/llvm/test/Transforms/TailCallElim/debugloc.ll index 3abbd6552efc..49957695a421 100644 --- a/llvm/test/Transforms/TailCallElim/debugloc.ll +++ b/llvm/test/Transforms/TailCallElim/debugloc.ll @@ -4,13 +4,13 @@ define void @foo() { entry: ; CHECK-LABEL: entry: -; CHECK: br label %tailrecurse, !dbg ![[DbgLoc:[0-9]+]] +; CHECK: br label %tailrecurse{{$}} call void @foo() ;; line 1 ret void ; CHECK-LABEL: tailrecurse: -; CHECK: br label %tailrecurse, !dbg ![[DbgLoc]] +; CHECK: br label %tailrecurse, !dbg ![[DbgLoc:[0-9]+]] } ;; Make sure tailrecurse has the call instruction's DL -- GitLab From 856e815ca1c416de263438e90e8120947e33a03c Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Thu, 28 Mar 2024 18:08:59 +0800 Subject: [PATCH 173/541] [DAGCombiner] Set disjoint flag in add->or and xor->or combines (#86925) We check DAG.haveNoCommonBitsSet so the operands will be known to be disjoint. I couldn't think of a codegen test case since most targets aren't checking hasDisjoint yet, apart from RISCV in the or_is_add pattern, but it also falls back to computeKnownBits. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 14 ++++++++++---- .../Inputs/lanai_isel.ll.expected | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 36abe27d2621..6dd3fbb3c97e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2887,8 +2887,11 @@ SDValue DAGCombiner::visitADD(SDNode *N) { // fold (a+b) -> (a|b) iff a and b share no bits. if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) && - DAG.haveNoCommonBitsSet(N0, N1)) - return DAG.getNode(ISD::OR, DL, VT, N0, N1); + DAG.haveNoCommonBitsSet(N0, N1)) { + SDNodeFlags Flags; + Flags.setDisjoint(true); + return DAG.getNode(ISD::OR, DL, VT, N0, N1, Flags); + } // Fold (add (vscale * C0), (vscale * C1)) to (vscale * (C0 + C1)). if (N0.getOpcode() == ISD::VSCALE && N1.getOpcode() == ISD::VSCALE) { @@ -9289,8 +9292,11 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { // fold (a^b) -> (a|b) iff a and b share no bits. if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) && - DAG.haveNoCommonBitsSet(N0, N1)) - return DAG.getNode(ISD::OR, DL, VT, N0, N1); + DAG.haveNoCommonBitsSet(N0, N1)) { + SDNodeFlags Flags; + Flags.setDisjoint(true); + return DAG.getNode(ISD::OR, DL, VT, N0, N1, Flags); + } // look for 'add-like' folds: // XOR(N0,MIN_SIGNED_VALUE) == ADD(N0,MIN_SIGNED_VALUE) diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected index 80145c5e098e..71e82eca6c3e 100644 --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected @@ -7,7 +7,7 @@ define i64 @i64_test(i64 %i) nounwind readnone { ; CHECK-NEXT: t0: ch,glue = EntryToken ; CHECK-NEXT: t5: i32,ch = LDW_RI TargetFrameIndex:i32<-2>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t7: i32 = ADD_I_LO TargetFrameIndex:i32<0>, TargetConstant:i32<0> -; CHECK-NEXT: t29: i32 = OR_I_LO t7, TargetConstant:i32<4> +; CHECK-NEXT: t29: i32 = OR_I_LO disjoint t7, TargetConstant:i32<4> ; CHECK-NEXT: t22: i32,ch = LDW_RI t29, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t24: i32 = ADD_R t5, t22, TargetConstant:i32<0> ; CHECK-NEXT: t3: i32,ch = LDW_RI TargetFrameIndex:i32<-1>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 @@ -52,7 +52,7 @@ define i64 @i16_test(i16 %i) nounwind readnone { ; CHECK-NEXT: t33: i32,ch = CopyFromReg t0, Register:i32 $r0 ; CHECK-NEXT: t14: ch,glue = CopyToReg t0, Register:i32 $rv, t33 ; CHECK-NEXT: t1: i32 = ADD_I_LO TargetFrameIndex:i32<-1>, TargetConstant:i32<0> -; CHECK-NEXT: t21: i32 = OR_I_LO t1, TargetConstant:i32<2> +; CHECK-NEXT: t21: i32 = OR_I_LO disjoint t1, TargetConstant:i32<2> ; CHECK-NEXT: t23: i32,ch = LDHz_RI t21, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t22: i32,ch = LDHz_RI TargetFrameIndex:i32<0>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t24: i32 = ADD_R t23, t22, TargetConstant:i32<0> @@ -75,7 +75,7 @@ define i64 @i8_test(i8 %i) nounwind readnone { ; CHECK-NEXT: t33: i32,ch = CopyFromReg t0, Register:i32 $r0 ; CHECK-NEXT: t14: ch,glue = CopyToReg t0, Register:i32 $rv, t33 ; CHECK-NEXT: t1: i32 = ADD_I_LO TargetFrameIndex:i32<-1>, TargetConstant:i32<0> -; CHECK-NEXT: t21: i32 = OR_I_LO t1, TargetConstant:i32<3> +; CHECK-NEXT: t21: i32 = OR_I_LO disjoint t1, TargetConstant:i32<3> ; CHECK-NEXT: t23: i32,ch = LDBz_RI t21, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t22: i32,ch = LDBz_RI TargetFrameIndex:i32<0>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t24: i32 = ADD_R t23, t22, TargetConstant:i32<0> -- GitLab From e640d9e725ef06b9787ab0ab884598f4f5532e48 Mon Sep 17 00:00:00 2001 From: bvlgah Date: Thu, 28 Mar 2024 18:09:18 +0800 Subject: [PATCH 174/541] =?UTF-8?q?[RISCV][GlobalISel]=20Fix=20legalizing?= =?UTF-8?q?=20=E2=80=98llvm.va=5Fcopy=E2=80=99=20intrinsic=20(#86863)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi, I spotted a problem when running benchmarking programs on a RISCV64 device. ## Issue Segmentation faults only occurred while running the programs compiled with `GlobalISel` enabled. Here is a small but complete example (it is adopted from [Google's benchmark framework](https://github.com/llvm/llvm-test-suite/blob/95a9f0d0b45056274f0bb4b0e0dd019023e414dc/MicroBenchmarks/libs/benchmark/src/colorprint.cc#L85-L119) to reproduce the issue, ```cpp #include #include #include #include #include std::string FormatString(const char* msg, va_list args) { // we might need a second shot at this, so pre-emptivly make a copy va_list args_cp; va_copy(args_cp, args); std::size_t size = 256; char local_buff[256]; auto ret = vsnprintf(local_buff, size, msg, args_cp); va_end(args_cp); // currently there is no error handling for failure, so this is hack. // BM_CHECK(ret >= 0); if (ret == 0) // handle empty expansion return {}; else if (static_cast(ret) < size) return local_buff; else { // we did not provide a long enough buffer on our first attempt. size = static_cast(ret) + 1; // + 1 for the null byte std::unique_ptr buff(new char[size]); ret = vsnprintf(buff.get(), size, msg, args); // BM_CHECK(ret > 0 && (static_cast(ret)) < size); return buff.get(); } } std::string FormatString(const char* msg, ...) { va_list args; va_start(args, msg); auto tmp = FormatString(msg, args); va_end(args); return tmp; } int main() { std::string Str = FormatString("%-*s %13s %15s %12s", static_cast(20), "Benchmark", "Time", "CPU", "Iterations"); std::cout << Str << std::endl; } ``` Use `clang++ -fglobal-isel -o main main.cpp` to compile it. ## Cause I have examined MIR, it shows that these segmentation faults resulted from a small mistake about legalizing the intrinsic function `llvm.va_copy`. https://github.com/llvm/llvm-project/blob/36e74cfdbde208e384c72bcb52ea638303fb7d67/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp#L451-L453 `DstLst` and `Tmp` are placed in the wrong order. ## Changes I have tweaked the test case `CodeGen/RISCV/GlobalISel/vararg.ll` so that `s0` is used as the frame pointer (not in all checks) which points to the starting address of the save area. I believe that it helps reason about how `llvm.va_copy` is handled. --- .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 2 +- .../GlobalISel/legalizer/legalize-vacopy.mir | 2 +- llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll | 936 +++++++++++++++++- 3 files changed, 933 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index 9a388f4cd271..22cae389cc33 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -450,7 +450,7 @@ bool RISCVLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper, // Store the result in the destination va_list MachineMemOperand *StoreMMO = MF.getMachineMemOperand( MachinePointerInfo(), MachineMemOperand::MOStore, PtrTy, Alignment); - MIRBuilder.buildStore(DstLst, Tmp, *StoreMMO); + MIRBuilder.buildStore(Tmp, DstLst, *StoreMMO); MI.eraseFromParent(); return true; diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir index f9eda1252937..16542f580012 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir @@ -14,7 +14,7 @@ body: | ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[COPY1]](p0) :: (load (p0)) - ; CHECK-NEXT: G_STORE [[COPY]](p0), [[LOAD]](p0) :: (store (p0)) + ; CHECK-NEXT: G_STORE [[LOAD]](p0), [[COPY]](p0) :: (store (p0)) ; CHECK-NEXT: PseudoRET %0:_(p0) = COPY $x10 %1:_(p0) = COPY $x11 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll index 7b110e562e05..d55adf371119 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll @@ -17,6 +17,12 @@ ; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel -mattr=+d -target-abi lp64d \ ; RUN: -verify-machineinstrs \ ; RUN: | FileCheck -check-prefixes=RV64,LP64D %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv32 -global-isel \ +; RUN: -frame-pointer=all -target-abi ilp32 -verify-machineinstrs \ +; RUN: | FileCheck -check-prefixes=RV32-WITHFP %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel \ +; RUN: -frame-pointer=all -target-abi lp64 -verify-machineinstrs \ +; RUN: | FileCheck -check-prefixes=RV64-WITHFP %s ; The same vararg calling convention is used for ilp32/ilp32f/ilp32d and for ; lp64/lp64f/lp64d. Different CHECK lines are required due to slight @@ -79,6 +85,67 @@ define i32 @va1(ptr %fmt, ...) { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: lw a0, -20(s0) +; RV64-WITHFP-NEXT: lwu a1, -24(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: or a0, a0, a1 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: srli a2, a1, 32 +; RV64-WITHFP-NEXT: sw a1, -24(s0) +; RV64-WITHFP-NEXT: sw a2, -20(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va, align 4 @@ -131,6 +198,58 @@ define i32 @va1_va_arg(ptr %fmt, ...) nounwind { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -212,6 +331,78 @@ define i32 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 96 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_va_arg_alloca: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw s1, 0(a0) +; RV32-WITHFP-NEXT: addi a0, s1, 15 +; RV32-WITHFP-NEXT: andi a0, a0, -16 +; RV32-WITHFP-NEXT: sub a0, sp, a0 +; RV32-WITHFP-NEXT: mv sp, a0 +; RV32-WITHFP-NEXT: call notdead +; RV32-WITHFP-NEXT: mv a0, s1 +; RV32-WITHFP-NEXT: addi sp, s0, -16 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_va_arg_alloca: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: lw s1, 0(a0) +; RV64-WITHFP-NEXT: slli a0, s1, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: andi a0, a0, -16 +; RV64-WITHFP-NEXT: sub a0, sp, a0 +; RV64-WITHFP-NEXT: mv sp, a0 +; RV64-WITHFP-NEXT: call notdead +; RV64-WITHFP-NEXT: mv a0, s1 +; RV64-WITHFP-NEXT: addi sp, s0, -32 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -273,6 +464,36 @@ define void @va1_caller() nounwind { ; LP64D-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; LP64D-NEXT: addi sp, sp, 16 ; LP64D-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: lui a3, 261888 +; RV32-WITHFP-NEXT: li a4, 2 +; RV32-WITHFP-NEXT: li a2, 0 +; RV32-WITHFP-NEXT: call va1 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: lui a0, %hi(.LCPI3_0) +; RV64-WITHFP-NEXT: ld a1, %lo(.LCPI3_0)(a0) +; RV64-WITHFP-NEXT: li a2, 2 +; RV64-WITHFP-NEXT: call va1 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i32 (ptr, ...) @va1(ptr undef, double 1.0, i32 2) ret void } @@ -395,6 +616,59 @@ define i64 @va2(ptr %fmt, ...) nounwind { ; RV64-NEXT: ld a0, 0(a1) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 7 +; RV32-WITHFP-NEXT: andi a1, a0, -8 +; RV32-WITHFP-NEXT: addi a0, a0, 8 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a1) +; RV32-WITHFP-NEXT: lw a1, 4(a1) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a1, a0, 7 +; RV64-WITHFP-NEXT: andi a1, a1, -8 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, 0(a1) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va @@ -459,6 +733,61 @@ define i64 @va2_va_arg(ptr %fmt, ...) nounwind { ; RV64-NEXT: srli a0, a0, 32 ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: li a1, 0 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -487,6 +816,32 @@ define void @va2_caller() nounwind { ; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 16 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: li a1, 1 +; RV32-WITHFP-NEXT: call va2 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: li a1, 1 +; RV64-WITHFP-NEXT: call va2 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i64 (ptr, ...) @va2(ptr undef, i32 1) ret void } @@ -617,6 +972,61 @@ define i64 @va3(i32 %a, i64 %b, ...) nounwind { ; RV64-NEXT: add a0, a1, a0 ; RV64-NEXT: addi sp, sp, 64 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 16(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 24 +; RV32-WITHFP-NEXT: sw a3, 4(s0) +; RV32-WITHFP-NEXT: sw a4, 8(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 12(s0) +; RV32-WITHFP-NEXT: sw a6, 16(s0) +; RV32-WITHFP-NEXT: sw a7, 20(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 7 +; RV32-WITHFP-NEXT: andi a3, a0, -8 +; RV32-WITHFP-NEXT: addi a0, a0, 8 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a4, 0(a3) +; RV32-WITHFP-NEXT: lw a3, 4(a3) +; RV32-WITHFP-NEXT: add a0, a1, a4 +; RV32-WITHFP-NEXT: sltu a1, a0, a4 +; RV32-WITHFP-NEXT: add a2, a2, a3 +; RV32-WITHFP-NEXT: add a1, a2, a1 +; RV32-WITHFP-NEXT: lw ra, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 16(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -80 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a2, 0(s0) +; RV64-WITHFP-NEXT: sd a3, 8(s0) +; RV64-WITHFP-NEXT: sd a4, 16(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 24(s0) +; RV64-WITHFP-NEXT: sd a6, 32(s0) +; RV64-WITHFP-NEXT: sd a7, 40(s0) +; RV64-WITHFP-NEXT: addi a2, a0, 7 +; RV64-WITHFP-NEXT: andi a2, a2, -8 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, 0(a2) +; RV64-WITHFP-NEXT: add a0, a1, a0 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 80 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va @@ -682,6 +1092,61 @@ define i64 @va3_va_arg(i32 %a, i64 %b, ...) nounwind { ; RV64-NEXT: add a0, a1, a0 ; RV64-NEXT: addi sp, sp, 64 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 16(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 24 +; RV32-WITHFP-NEXT: sw a3, 4(s0) +; RV32-WITHFP-NEXT: sw a4, 8(s0) +; RV32-WITHFP-NEXT: sw a5, 12(s0) +; RV32-WITHFP-NEXT: sw a6, 16(s0) +; RV32-WITHFP-NEXT: sw a7, 20(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a3, a0, 4 +; RV32-WITHFP-NEXT: sw a3, -12(s0) +; RV32-WITHFP-NEXT: lw a3, 0(a0) +; RV32-WITHFP-NEXT: add a0, a1, a3 +; RV32-WITHFP-NEXT: sltu a1, a0, a3 +; RV32-WITHFP-NEXT: add a1, a2, a1 +; RV32-WITHFP-NEXT: lw ra, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 16(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -80 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a2, 0(s0) +; RV64-WITHFP-NEXT: sd a3, 8(s0) +; RV64-WITHFP-NEXT: sd a4, 16(s0) +; RV64-WITHFP-NEXT: sd a5, 24(s0) +; RV64-WITHFP-NEXT: sd a6, 32(s0) +; RV64-WITHFP-NEXT: sd a7, 40(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a2, a0, 4 +; RV64-WITHFP-NEXT: sd a2, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: add a0, a1, a0 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 80 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -718,6 +1183,39 @@ define void @va3_caller() nounwind { ; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 16 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: lui a0, 5 +; RV32-WITHFP-NEXT: addi a3, a0, -480 +; RV32-WITHFP-NEXT: li a0, 2 +; RV32-WITHFP-NEXT: li a1, 1111 +; RV32-WITHFP-NEXT: li a2, 0 +; RV32-WITHFP-NEXT: call va3 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: lui a0, 5 +; RV64-WITHFP-NEXT: addiw a2, a0, -480 +; RV64-WITHFP-NEXT: li a0, 2 +; RV64-WITHFP-NEXT: li a1, 1111 +; RV64-WITHFP-NEXT: call va3 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i64 (i32, i64, ...) @va3(i32 2, i64 1111, i32 20000) ret void } @@ -745,9 +1243,8 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV32-NEXT: addi a1, a0, 4 ; RV32-NEXT: sw a1, 4(sp) ; RV32-NEXT: lw a1, 4(sp) -; RV32-NEXT: mv a2, sp ; RV32-NEXT: lw s0, 0(a0) -; RV32-NEXT: sw a2, 0(a1) +; RV32-NEXT: sw a1, 0(sp) ; RV32-NEXT: lw a0, 0(sp) ; RV32-NEXT: call notdead ; RV32-NEXT: lw a0, 4(sp) @@ -796,9 +1293,8 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV64-NEXT: addi a1, a0, 4 ; RV64-NEXT: sd a1, 8(sp) ; RV64-NEXT: ld a1, 8(sp) -; RV64-NEXT: mv a2, sp ; RV64-NEXT: lw s0, 0(a0) -; RV64-NEXT: sd a2, 0(a1) +; RV64-NEXT: sd a1, 0(sp) ; RV64-NEXT: lw a0, 4(sp) ; RV64-NEXT: lwu a1, 0(sp) ; RV64-NEXT: slli a0, a0, 32 @@ -829,6 +1325,115 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 96 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va4_va_copy: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -64 +; RV32-WITHFP-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 24(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s1, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a1, -16(s0) +; RV32-WITHFP-NEXT: lw s1, 0(a0) +; RV32-WITHFP-NEXT: sw a1, -20(s0) +; RV32-WITHFP-NEXT: lw a0, -20(s0) +; RV32-WITHFP-NEXT: call notdead +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: addi a1, a1, 3 +; RV32-WITHFP-NEXT: andi a1, a1, -4 +; RV32-WITHFP-NEXT: addi a2, a1, 4 +; RV32-WITHFP-NEXT: sw a2, -16(s0) +; RV32-WITHFP-NEXT: lw a2, -16(s0) +; RV32-WITHFP-NEXT: lw a1, 0(a1) +; RV32-WITHFP-NEXT: addi a2, a2, 3 +; RV32-WITHFP-NEXT: andi a2, a2, -4 +; RV32-WITHFP-NEXT: addi a3, a2, 4 +; RV32-WITHFP-NEXT: sw a3, -16(s0) +; RV32-WITHFP-NEXT: lw a2, 0(a2) +; RV32-WITHFP-NEXT: add a0, a0, s1 +; RV32-WITHFP-NEXT: add a1, a1, a2 +; RV32-WITHFP-NEXT: add a0, a0, a1 +; RV32-WITHFP-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 24(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s1, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 64 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va4_va_copy: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -112 +; RV64-WITHFP-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s1, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 48 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: ld a1, -32(s0) +; RV64-WITHFP-NEXT: lw s1, 0(a0) +; RV64-WITHFP-NEXT: sd a1, -40(s0) +; RV64-WITHFP-NEXT: lw a0, -36(s0) +; RV64-WITHFP-NEXT: lwu a1, -40(s0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: or a0, a0, a1 +; RV64-WITHFP-NEXT: call notdead +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: ld a1, -32(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: addi a1, a1, 3 +; RV64-WITHFP-NEXT: andi a1, a1, -4 +; RV64-WITHFP-NEXT: addi a2, a1, 4 +; RV64-WITHFP-NEXT: sd a2, -32(s0) +; RV64-WITHFP-NEXT: ld a2, -32(s0) +; RV64-WITHFP-NEXT: lw a1, 0(a1) +; RV64-WITHFP-NEXT: addi a2, a2, 3 +; RV64-WITHFP-NEXT: andi a2, a2, -4 +; RV64-WITHFP-NEXT: addi a3, a2, 4 +; RV64-WITHFP-NEXT: sd a3, -32(s0) +; RV64-WITHFP-NEXT: lw a2, 0(a2) +; RV64-WITHFP-NEXT: add a0, a0, s1 +; RV64-WITHFP-NEXT: add a1, a1, a2 +; RV64-WITHFP-NEXT: addw a0, a0, a1 +; RV64-WITHFP-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s1, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 112 +; RV64-WITHFP-NEXT: ret %vargs = alloca ptr %wargs = alloca ptr call void @llvm.va_start(ptr %vargs) @@ -899,6 +1504,60 @@ define i32 @va6_no_fixed_args(...) nounwind { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va6_no_fixed_args: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a0, 0(s0) +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: mv a0, s0 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va6_no_fixed_args: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a0, 0(s0) +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -993,6 +1652,85 @@ define i32 @va_large_stack(ptr %fmt, ...) { ; RV64-NEXT: addiw a1, a1, 336 ; RV64-NEXT: add sp, sp, a1 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_large_stack: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -2032 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 2032 +; RV32-WITHFP-NEXT: sw ra, 1996(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 1992(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 2000 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: lui a0, 24414 +; RV32-WITHFP-NEXT: addi a0, a0, -1728 +; RV32-WITHFP-NEXT: sub sp, sp, a0 +; RV32-WITHFP-NEXT: lui a0, 24414 +; RV32-WITHFP-NEXT: addi a0, a0, 272 +; RV32-WITHFP-NEXT: sub a0, s0, a0 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a1, s0, 4 +; RV32-WITHFP-NEXT: sw a1, 0(a0) +; RV32-WITHFP-NEXT: lw a1, 0(a0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a2, a1, 4 +; RV32-WITHFP-NEXT: sw a2, 0(a0) +; RV32-WITHFP-NEXT: lw a0, 0(a1) +; RV32-WITHFP-NEXT: lui a1, 24414 +; RV32-WITHFP-NEXT: addi a1, a1, -1728 +; RV32-WITHFP-NEXT: add sp, sp, a1 +; RV32-WITHFP-NEXT: lw ra, 1996(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 1992(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 2032 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_large_stack: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -2032 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 2032 +; RV64-WITHFP-NEXT: sd ra, 1960(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 1952(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 1968 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: lui a0, 24414 +; RV64-WITHFP-NEXT: addiw a0, a0, -1680 +; RV64-WITHFP-NEXT: sub sp, sp, a0 +; RV64-WITHFP-NEXT: lui a0, 24414 +; RV64-WITHFP-NEXT: addiw a0, a0, 288 +; RV64-WITHFP-NEXT: sub a0, s0, a0 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: addi a1, s0, 8 +; RV64-WITHFP-NEXT: sd a1, 0(a0) +; RV64-WITHFP-NEXT: lw a1, 4(a0) +; RV64-WITHFP-NEXT: lwu a2, 0(a0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: slli a1, a1, 32 +; RV64-WITHFP-NEXT: or a1, a1, a2 +; RV64-WITHFP-NEXT: addi a2, a1, 4 +; RV64-WITHFP-NEXT: srli a3, a2, 32 +; RV64-WITHFP-NEXT: sw a2, 0(a0) +; RV64-WITHFP-NEXT: sw a3, 4(a0) +; RV64-WITHFP-NEXT: lw a0, 0(a1) +; RV64-WITHFP-NEXT: lui a1, 24414 +; RV64-WITHFP-NEXT: addiw a1, a1, -1680 +; RV64-WITHFP-NEXT: add sp, sp, a1 +; RV64-WITHFP-NEXT: ld ra, 1960(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 1952(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 2032 +; RV64-WITHFP-NEXT: ret %large = alloca [ 100000000 x i8 ] %va = alloca ptr call void @llvm.va_start(ptr %va) @@ -1004,5 +1742,193 @@ define i32 @va_large_stack(ptr %fmt, ...) { ret i32 %1 } +define i32 @va_vprintf(ptr %fmt, ptr %arg_start) { +; RV32-LABEL: va_vprintf: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw a1, 12(sp) +; RV32-NEXT: lw a0, 12(sp) +; RV32-NEXT: sw a0, 8(sp) +; RV32-NEXT: lw a0, 8(sp) +; RV32-NEXT: addi a0, a0, 3 +; RV32-NEXT: andi a0, a0, -4 +; RV32-NEXT: addi a1, a0, 4 +; RV32-NEXT: sw a1, 8(sp) +; RV32-NEXT: lw a0, 0(a0) +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: va_vprintf: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd a1, 8(sp) +; RV64-NEXT: ld a0, 8(sp) +; RV64-NEXT: sd a0, 0(sp) +; RV64-NEXT: ld a0, 0(sp) +; RV64-NEXT: addi a0, a0, 3 +; RV64-NEXT: andi a0, a0, -4 +; RV64-NEXT: addi a1, a0, 4 +; RV64-NEXT: sd a1, 0(sp) +; RV64-NEXT: lw a0, 0(a0) +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_vprintf: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -4 +; RV32-WITHFP-NEXT: .cfi_offset s0, -8 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 0 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_vprintf: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -32 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 32 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -8 +; RV64-WITHFP-NEXT: .cfi_offset s0, -16 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 0 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 32 +; RV64-WITHFP-NEXT: ret + %args = alloca ptr + %args_cp = alloca ptr + store ptr %arg_start, ptr %args + call void @llvm.va_copy(ptr %args_cp, ptr %args) + %width = va_arg ptr %args_cp, i32 + call void @llvm.va_end(ptr %args_cp) + ret i32 %width +} - +define i32 @va_printf(ptr %fmt, ...) { +; RV32-LABEL: va_printf: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -48 +; RV32-NEXT: .cfi_def_cfa_offset 48 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -36 +; RV32-NEXT: sw a1, 20(sp) +; RV32-NEXT: sw a2, 24(sp) +; RV32-NEXT: sw a3, 28(sp) +; RV32-NEXT: sw a4, 32(sp) +; RV32-NEXT: addi a1, sp, 20 +; RV32-NEXT: sw a1, 8(sp) +; RV32-NEXT: lw a1, 8(sp) +; RV32-NEXT: sw a5, 36(sp) +; RV32-NEXT: sw a6, 40(sp) +; RV32-NEXT: sw a7, 44(sp) +; RV32-NEXT: call va_vprintf +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 48 +; RV32-NEXT: ret +; +; RV64-LABEL: va_printf: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -80 +; RV64-NEXT: .cfi_def_cfa_offset 80 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -72 +; RV64-NEXT: sd a1, 24(sp) +; RV64-NEXT: sd a2, 32(sp) +; RV64-NEXT: sd a3, 40(sp) +; RV64-NEXT: sd a4, 48(sp) +; RV64-NEXT: addi a1, sp, 24 +; RV64-NEXT: sd a1, 0(sp) +; RV64-NEXT: ld a1, 0(sp) +; RV64-NEXT: sd a5, 56(sp) +; RV64-NEXT: sd a6, 64(sp) +; RV64-NEXT: sd a7, 72(sp) +; RV64-NEXT: call va_vprintf +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 80 +; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_printf: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a1, s0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a1, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: call va_vprintf +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_printf: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: addi a1, s0, 8 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: ld a1, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: call va_vprintf +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret + %args = alloca ptr + call void @llvm.va_start(ptr %args) + %arg_start = load ptr, ptr %args + %ret_val = call i32 @va_vprintf(ptr %fmt, ptr %arg_start) + call void @llvm.va_end(ptr %args) + ret i32 %ret_val +} -- GitLab From 8963a476ccb7ef2944eedaf8813458561e29b465 Mon Sep 17 00:00:00 2001 From: Shan Huang <52285902006@stu.ecnu.edu.cn> Date: Thu, 28 Mar 2024 18:24:18 +0800 Subject: [PATCH 175/541] Fix #86269: remove unused variable (#86927) Remove the unused variable `BI` introduced in #86269. --- llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index 34d39f3fe6dc..bc4b6de2f07f 100644 --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -509,10 +509,10 @@ void TailRecursionEliminator::createTailRecurseLoopHeader(CallInst *CI) { BasicBlock *NewEntry = BasicBlock::Create(F.getContext(), "", &F, HeaderBB); NewEntry->takeName(HeaderBB); HeaderBB->setName("tailrecurse"); - BranchInst *BI = BranchInst::Create(HeaderBB, NewEntry); + BranchInst::Create(HeaderBB, NewEntry); // If the new branch preserves the debug location of CI, it could result in // misleading stepping, if CI is located in a conditional branch. - // So, here we don't give any debug location to BI. + // So, here we don't give any debug location to the new branch. // Move all fixed sized allocas from HeaderBB to NewEntry. for (BasicBlock::iterator OEBI = HeaderBB->begin(), E = HeaderBB->end(), -- GitLab From 8a7f021f9e183c95f3eb17a27cbb219e204f3b25 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 28 Mar 2024 10:37:31 +0000 Subject: [PATCH 176/541] [GitHub] Fix typos in automation (#86886) --- llvm/utils/git/github-automation.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/utils/git/github-automation.py b/llvm/utils/git/github-automation.py index 42a658cefac3..1b5141e42594 100755 --- a/llvm/utils/git/github-automation.py +++ b/llvm/utils/git/github-automation.py @@ -36,7 +36,7 @@ If you have any further questions about this issue, don't hesitate to ask via a """ -def _get_curent_team(team_name, teams) -> Optional[github.Team.Team]: +def _get_current_team(team_name, teams) -> Optional[github.Team.Team]: for team in teams: if team_name == team.name.lower(): return team @@ -70,7 +70,7 @@ class IssueSubscriber: self._team_name = "issue-subscribers-{}".format(label_name).lower() def run(self) -> bool: - team = _get_curent_team(self.team_name, self.org.get_teams()) + team = _get_current_team(self.team_name, self.org.get_teams()) if not team: print(f"couldn't find team named {self.team_name}") return False @@ -125,7 +125,7 @@ class PRSubscriber: def run(self) -> bool: patch = None - team = _get_curent_team(self.team_name, self.org.get_teams()) + team = _get_current_team(self.team_name, self.org.get_teams()) if not team: print(f"couldn't find team named {self.team_name}") return False @@ -201,7 +201,7 @@ Author: {self.pr.user.name} ({self.pr.user.login}) ) return True - def _get_curent_team(self) -> Optional[github.Team.Team]: + def _get_current_team(self) -> Optional[github.Team.Team]: for team in self.org.get_teams(): if self.team_name == team.name.lower(): return team @@ -281,7 +281,7 @@ class PRBuildbotInformation: @{self.author} Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested -by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may recieve a report in an email or a comment on this PR. +by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your @@ -639,7 +639,7 @@ class ReleaseWorkflow: parser = argparse.ArgumentParser() parser.add_argument( - "--token", type=str, required=True, help="GitHub authentiation token" + "--token", type=str, required=True, help="GitHub authentication token" ) parser.add_argument( "--repo", @@ -669,7 +669,7 @@ release_workflow_parser.add_argument( "--llvm-project-dir", type=str, default=".", - help="directory containing the llvm-project checout", + help="directory containing the llvm-project checkout", ) release_workflow_parser.add_argument( "--issue-number", type=int, required=True, help="The issue number to update" -- GitLab From 79ba323bdd0843275019e16b6e9b35133677c514 Mon Sep 17 00:00:00 2001 From: Shan Huang <52285902006@stu.ecnu.edu.cn> Date: Thu, 28 Mar 2024 18:43:03 +0800 Subject: [PATCH 177/541] [Debuginfo][GVNHoist] Fix #86227: update the debug location of the hoisted GEP (#86236) This PR fixes #86227. --- llvm/lib/Transforms/Scalar/GVNHoist.cpp | 8 +++ .../Transforms/GVNHoist/hoist-merge-geps.ll | 63 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 llvm/test/Transforms/GVNHoist/hoist-merge-geps.ll diff --git a/llvm/lib/Transforms/Scalar/GVNHoist.cpp b/llvm/lib/Transforms/Scalar/GVNHoist.cpp index b564f00eb9d1..261c1259c9c9 100644 --- a/llvm/lib/Transforms/Scalar/GVNHoist.cpp +++ b/llvm/lib/Transforms/Scalar/GVNHoist.cpp @@ -951,6 +951,14 @@ void GVNHoist::makeGepsAvailable(Instruction *Repl, BasicBlock *HoistPt, OtherGep = cast( cast(OtherInst)->getPointerOperand()); ClonedGep->andIRFlags(OtherGep); + + // Merge debug locations of GEPs, because the hoisted GEP replaces those + // in branches. When cloning, ClonedGep preserves the debug location of + // Gepd, so Gep is skipped to avoid merging it twice. + if (OtherGep != Gep) { + ClonedGep->applyMergedLocation(ClonedGep->getDebugLoc(), + OtherGep->getDebugLoc()); + } } // Replace uses of Gep with ClonedGep in Repl. diff --git a/llvm/test/Transforms/GVNHoist/hoist-merge-geps.ll b/llvm/test/Transforms/GVNHoist/hoist-merge-geps.ll new file mode 100644 index 000000000000..b3b5916c7f26 --- /dev/null +++ b/llvm/test/Transforms/GVNHoist/hoist-merge-geps.ll @@ -0,0 +1,63 @@ +; RUN: opt -S -passes=gvn-hoist < %s | FileCheck %s + +define dso_local void @func(i32 noundef %a, ptr noundef %b) !dbg !10 { +; Check the merged debug location of hoisted GEP +; CHECK: entry +; CHECK: %{{[a-zA-Z0-9_]*}} = getelementptr {{.*}} !dbg [[MERGED_DL:![0-9]+]] +; CHECK: [[MERGED_DL]] = !DILocation(line: 0, scope: !{{[0-9]+}}) +entry: + tail call void @llvm.dbg.value(metadata i32 %a, metadata !16, metadata !DIExpression()), !dbg !17 + tail call void @llvm.dbg.value(metadata ptr %b, metadata !18, metadata !DIExpression()), !dbg !17 + %tobool = icmp ne i32 %a, 0, !dbg !19 + br i1 %tobool, label %if.then, label %if.else, !dbg !21 + +if.then: ; preds = %entry + %arrayidx = getelementptr inbounds i32, ptr %b, i64 1, !dbg !22 + store i32 1, ptr %arrayidx, align 4, !dbg !24 + br label %if.end, !dbg !25 + +if.else: ; preds = %entry + %arrayidx1 = getelementptr inbounds i32, ptr %b, i64 1, !dbg !26 + store i32 1, ptr %arrayidx1, align 4, !dbg !28 + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void, !dbg !29 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "main.c", directory: "/root/llvm-test/GVNHoist") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!10 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) +!11 = !DISubroutineType(types: !12) +!12 = !{null, !13, !14} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) +!15 = !{} +!16 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !1, line: 1, type: !13) +!17 = !DILocation(line: 0, scope: !10) +!18 = !DILocalVariable(name: "b", arg: 2, scope: !10, file: !1, line: 1, type: !14) +!19 = !DILocation(line: 2, column: 9, scope: !20) +!20 = distinct !DILexicalBlock(scope: !10, file: !1, line: 2, column: 9) +!21 = !DILocation(line: 2, column: 9, scope: !10) +!22 = !DILocation(line: 3, column: 9, scope: !23) +!23 = distinct !DILexicalBlock(scope: !20, file: !1, line: 2, column: 12) +!24 = !DILocation(line: 3, column: 14, scope: !23) +!25 = !DILocation(line: 4, column: 5, scope: !23) +!26 = !DILocation(line: 5, column: 9, scope: !27) +!27 = distinct !DILexicalBlock(scope: !20, file: !1, line: 4, column: 12) +!28 = !DILocation(line: 5, column: 14, scope: !27) +!29 = !DILocation(line: 7, column: 1, scope: !10) -- GitLab From 36b4b9d988ff1e82758fd5a462120086d21989e7 Mon Sep 17 00:00:00 2001 From: Freddy Ye Date: Thu, 28 Mar 2024 18:54:32 +0800 Subject: [PATCH 178/541] [X86] Support immediate folding for CCMP/CTEST (#86616) E.g. %0:gr32 = MOV32ri 81 CTEST32rr %0, %1, 2, 10, implicit-def $eflags, implicit $eflags => CTEST32ri %1, 81, 2, 10, implicit-def $eflags, implicit $eflags --- llvm/lib/Target/X86/X86InstrInfo.cpp | 9 ++- llvm/test/CodeGen/X86/apx/foldimmediate.mir | 70 +++++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/X86/apx/foldimmediate.mir diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index eb42a4b2119d..f24334312c11 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -5595,9 +5595,13 @@ static unsigned convertALUrr2ALUri(unsigned Opc) { case X86::FROM: \ return X86::TO; FROM_TO(TEST64rr, TEST64ri32) + FROM_TO(CTEST64rr, CTEST64ri32) FROM_TO(CMP64rr, CMP64ri32) + FROM_TO(CCMP64rr, CCMP64ri32) FROM_TO(TEST32rr, TEST32ri) + FROM_TO(CTEST32rr, CTEST32ri) FROM_TO(CMP32rr, CMP32ri) + FROM_TO(CCMP32rr, CCMP32ri) #undef FROM_TO } } @@ -5697,7 +5701,8 @@ bool X86InstrInfo::foldImmediateImpl(MachineInstr &UseMI, MachineInstr *DefMI, UseMI.findRegisterUseOperandIdx(Reg) != 2) return false; // For CMP instructions the immediate can only be at index 1. - if ((NewOpc == X86::CMP64ri32 || NewOpc == X86::CMP32ri) && + if (((NewOpc == X86::CMP64ri32 || NewOpc == X86::CMP32ri) || + (NewOpc == X86::CCMP64ri32 || NewOpc == X86::CCMP32ri)) && UseMI.findRegisterUseOperandIdx(Reg) != 1) return false; @@ -5742,7 +5747,7 @@ bool X86InstrInfo::foldImmediateImpl(MachineInstr &UseMI, MachineInstr *DefMI, unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex; unsigned ImmOpNum = 2; if (!UseMI.getOperand(0).isDef()) { - Op1 = 0; // TEST, CMP + Op1 = 0; // TEST, CMP, CTEST, CCMP ImmOpNum = 1; } if (Opc == TargetOpcode::COPY) diff --git a/llvm/test/CodeGen/X86/apx/foldimmediate.mir b/llvm/test/CodeGen/X86/apx/foldimmediate.mir new file mode 100644 index 000000000000..310fc64841f7 --- /dev/null +++ b/llvm/test/CodeGen/X86/apx/foldimmediate.mir @@ -0,0 +1,70 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3 +# RUN: llc -mtriple=x86_64-- -run-pass=peephole-opt %s -o - | FileCheck %s +--- | + define void @foldImmediate() { ret void } +... +--- +# Check that immediates can be folded into ALU instructions. +name: foldImmediate +registers: + - { id: 0, class: gr32 } + - { id: 1, class: gr32 } + - { id: 2, class: gr32 } + - { id: 3, class: gr32 } + - { id: 4, class: gr32 } + - { id: 5, class: gr32 } + - { id: 6, class: gr32 } + - { id: 7, class: gr64 } + - { id: 8, class: gr64 } + - { id: 9, class: gr64 } + - { id: 10, class: gr64 } + - { id: 11, class: gr64 } + - { id: 12, class: gr64 } + - { id: 13, class: gr64 } + - { id: 14, class: gr64 } + - { id: 15, class: gr64 } + - { id: 16, class: gr32 } + - { id: 17, class: gr64 } + - { id: 18, class: gr32 } + +body: | + bb.0: + liveins: $rdi, $rsi + + ; CHECK-LABEL: name: foldImmediate + ; CHECK: liveins: $rdi, $rsi + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 81 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi + ; CHECK-NEXT: CTEST32ri [[COPY]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: CCMP32ri [[COPY]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[MOV32ri]], %subreg.sub_32bit + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64 = COPY $rsi + ; CHECK-NEXT: CTEST64ri32 [[COPY1]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: CCMP64ri32 [[COPY1]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: CCMP64rr [[SUBREG_TO_REG]], [[COPY1]], 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + %0 = MOV32ri 81 + %1 = COPY $edi + + CTEST32rr %0, %1, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + + CCMP32rr %1, %0, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + + %7 = SUBREG_TO_REG 0, killed %0:gr32, %subreg.sub_32bit + %8 = COPY $rsi + + CTEST64rr %8, %7, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + + CCMP64rr %8, %7, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + CCMP64rr %7, %8, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags +... -- GitLab From 28b196e7fc4919a062ed20177d113cd0ae9b1f75 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 28 Mar 2024 10:41:02 +0100 Subject: [PATCH 179/541] [llvm] Write temporary test files into %t ... instead of the source tree --- lld/test/ELF/lto/libcall-archive.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lld/test/ELF/lto/libcall-archive.ll b/lld/test/ELF/lto/libcall-archive.ll index 84ddc1f55587..0f3d9c37d729 100644 --- a/lld/test/ELF/lto/libcall-archive.ll +++ b/lld/test/ELF/lto/libcall-archive.ll @@ -4,8 +4,8 @@ ; RUN: llvm-as -o %t2.o %S/Inputs/libcall-archive.ll ; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t3.o %S/Inputs/libcall-archive.s ; RUN: llvm-ar rcs %t.a %t2.o %t3.o -; RUN: ld.lld --why-extract=why.txt -o %t %t.o %t.a -; RUN: FileCheck %s --input-file=why.txt --check-prefix=CHECK-WHY +; RUN: ld.lld --why-extract=%t.why.txt -o %t %t.o %t.a +; RUN: FileCheck %s --input-file=%t.why.txt --check-prefix=CHECK-WHY ; RUN: llvm-nm %t | FileCheck %s ; RUN: ld.lld -o %t2 %t.o --start-lib %t2.o %t3.o --end-lib ; RUN: llvm-nm %t2 | FileCheck %s -- GitLab From b999e631c03640f7d1d93b5319da496ed4e0df55 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 28 Mar 2024 12:15:39 +0100 Subject: [PATCH 180/541] [OpenMP] Fix node destruction race in __kmpc_omp_taskwait_deps_51 (#86130) The __kmpc_omp_taskwait_deps_51 allocates a kmp_depnode_t node on its stack, and there is currently a race condition where another thread might still be accessing that node after the function has returned and its stack frame was released. While the function does wait until the node's npredecessors count has reached zero before exiting, there is still a window where the function that last decremented the npredecessors count assumes the node is still accessible. For heap-allocated kmp_depnode_t nodes, this normally works via a separate ndeps count that only reaches zero at the point where no accesses to the node are expected at all; in fact, at this point the heap allocation will be freed. For this case of a stack-allocated kmp_depnode_t node, it therefore makes sense to similarly respect the ndeps count; we need to wait until this reaches 1 (not 0, because it is not heap-allocated so there's always one extra count to prevent it from being freed), before we can safely deallocate our stack frame. As this is expected to be a short race window of only a few instructions, it should be fine to just use a busy wait loop checking the ndeps count. Fixes: https://github.com/llvm/llvm-project/issues/85963 --- openmp/runtime/src/kmp_taskdeps.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openmp/runtime/src/kmp_taskdeps.cpp b/openmp/runtime/src/kmp_taskdeps.cpp index f7529481393f..e575ad8b08a5 100644 --- a/openmp/runtime/src/kmp_taskdeps.cpp +++ b/openmp/runtime/src/kmp_taskdeps.cpp @@ -1030,6 +1030,12 @@ void __kmpc_omp_taskwait_deps_51(ident_t *loc_ref, kmp_int32 gtid, __kmp_task_stealing_constraint); } + // Wait until the last __kmp_release_deps is finished before we free the + // current stack frame holding the "node" variable; once its nrefs count + // reaches 1, we're sure nobody else can try to reference it again. + while (node.dn.nrefs > 1) + KMP_YIELD(TRUE); + #if OMPT_SUPPORT __ompt_taskwait_dep_finish(current_task, taskwait_task_data); #endif /* OMPT_SUPPORT */ -- GitLab From c13556c0b0aaeb9794d3e2864c8dd9880661f909 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 28 Mar 2024 14:27:14 +0300 Subject: [PATCH 181/541] AMDGPU: Document more backend recognized attributes (#80239) --- llvm/docs/AMDGPUUsage.rst | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 6e6d6b157148..22c1d1f186ea 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -1449,6 +1449,42 @@ The AMDGPU backend supports the following LLVM IR attributes. the frame. This is an internal detail of how LDS variables are lowered, language front ends should not set this attribute. + "amdgpu-gds-size" Bytes expected to be allocated at the start of GDS memory at entry. + + "amdgpu-git-ptr-high" The hard-wired high half of the address of the global information table + for AMDPAL OS type. 0xffffffff represents no hard-wired high half, since + current hardware only allows a 16 bit value. + + "amdgpu-32bit-address-high-bits" Assumed high 32-bits for 32-bit address spaces which are really truncated + 64-bit addresses (i.e., addrspace(6)) + + "amdgpu-color-export" Indicates shader exports color information if set to 1. + Defaults to 1 for :ref:`amdgpu_ps `, and 0 for other calling + conventions. Determines the necessity and type of null exports when a shader + terminates early by killing lanes. + + "amdgpu-depth-export" Indicates shader exports depth information if set to 1. Determines the + necessity and type of null exports when a shader terminates early by killing + lanes. A depth-only shader will export to depth channel when no null export + target is available (GFX11+). + + "InitialPSInputAddr" Set the initial value of the `spi_ps_input_addr` register for + :ref:`amdgpu_ps ` shaders. Any bits enabled by this value will + be enabled in the final register value. + + "amdgpu-wave-priority-threshold" VALU instruction count threshold for adjusting wave priority. If exceeded, + temporarily raise the wave priority at the start of the shader function + until its last VMEM instructions to allow younger waves to issue their VMEM + instructions as well. + + "amdgpu-memory-bound" Set internally by backend + + "amdgpu-wave-limiter" Set internally by backend + + "amdgpu-unroll-threshold" Set base cost threshold preference for loop unrolling within this function, + default is 300. Actual threshold may be varied by per-loop metadata or + reduced by heuristics. + "amdgpu-max-num-workgroups"="x,y,z" Specify the maximum number of work groups for the kernel dispatch in the X, Y, and Z dimensions. Generated by the ``amdgpu_max_num_work_groups`` CLANG attribute [CLANG-ATTR]_. Clang only emits this attribute when all -- GitLab From c9db031c48852af491747dab86ef6f19195eb20d Mon Sep 17 00:00:00 2001 From: Andrew Ng Date: Thu, 28 Mar 2024 11:41:49 +0000 Subject: [PATCH 182/541] [Support] Fix color handling in formatted_raw_ostream (#86700) The color methods in formatted_raw_ostream were forwarding directly to the underlying stream without considering existing buffered output. This would cause incorrect colored output for buffered uses of formatted_raw_ostream. Fix this issue by applying the color to the formatted_raw_ostream itself and temporarily disabling scanning of any color related output so as not to affect the position tracking. This fix means that workarounds that forced formatted_raw_ostream buffering to be disabled can be removed. In the case of llvm-objdump, this can improve disassembly performance when redirecting to a file by more than an order of magnitude on both Windows and Linux. This improvement restores the disassembly performance when redirecting to a file to a level similar to before color support was added. --- llvm/include/llvm/Support/FormattedStream.h | 51 ++++++++++++++++++--- llvm/lib/Support/FormattedStream.cpp | 3 ++ llvm/tools/llvm-mc/llvm-mc.cpp | 5 -- llvm/tools/llvm-objdump/llvm-objdump.cpp | 7 --- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/Support/FormattedStream.h b/llvm/include/llvm/Support/FormattedStream.h index 5f937cfa7984..850a18dbb941 100644 --- a/llvm/include/llvm/Support/FormattedStream.h +++ b/llvm/include/llvm/Support/FormattedStream.h @@ -52,6 +52,10 @@ class formatted_raw_ostream : public raw_ostream { /// have the rest of it. SmallString<4> PartialUTF8Char; + /// DisableScan - Temporarily disable scanning of output. Used to ignore color + /// codes. + bool DisableScan; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, @@ -89,9 +93,33 @@ class formatted_raw_ostream : public raw_ostream { SetUnbuffered(); TheStream->SetUnbuffered(); + enable_colors(TheStream->colors_enabled()); + Scanned = nullptr; } + void PreDisableScan() { + assert(!DisableScan); + ComputePosition(getBufferStart(), GetNumBytesInBuffer()); + assert(PartialUTF8Char.empty()); + DisableScan = true; + } + + void PostDisableScan() { + assert(DisableScan); + DisableScan = false; + Scanned = getBufferStart() + GetNumBytesInBuffer(); + } + + struct DisableScanScope { + formatted_raw_ostream *S; + + DisableScanScope(formatted_raw_ostream *FRO) : S(FRO) { + S->PreDisableScan(); + } + ~DisableScanScope() { S->PostDisableScan(); } + }; + public: /// formatted_raw_ostream - Open the specified file for /// writing. If an error occurs, information about the error is @@ -104,12 +132,12 @@ public: /// underneath it. /// formatted_raw_ostream(raw_ostream &Stream) - : TheStream(nullptr), Position(0, 0) { + : TheStream(nullptr), Position(0, 0), DisableScan(false) { setStream(Stream); } - explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { - Scanned = nullptr; - } + explicit formatted_raw_ostream() + : TheStream(nullptr), Position(0, 0), Scanned(nullptr), + DisableScan(false) {} ~formatted_raw_ostream() override { flush(); @@ -136,17 +164,26 @@ public: } raw_ostream &resetColor() override { - TheStream->resetColor(); + if (colors_enabled()) { + DisableScanScope S(this); + raw_ostream::resetColor(); + } return *this; } raw_ostream &reverseColor() override { - TheStream->reverseColor(); + if (colors_enabled()) { + DisableScanScope S(this); + raw_ostream::reverseColor(); + } return *this; } raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { - TheStream->changeColor(Color, Bold, BG); + if (colors_enabled()) { + DisableScanScope S(this); + raw_ostream::changeColor(Color, Bold, BG); + } return *this; } diff --git a/llvm/lib/Support/FormattedStream.cpp b/llvm/lib/Support/FormattedStream.cpp index c0d284350995..c50530e76efc 100644 --- a/llvm/lib/Support/FormattedStream.cpp +++ b/llvm/lib/Support/FormattedStream.cpp @@ -94,6 +94,9 @@ void formatted_raw_ostream::UpdatePosition(const char *Ptr, size_t Size) { /// ComputePosition - Examine the current output and update line and column /// counts. void formatted_raw_ostream::ComputePosition(const char *Ptr, size_t Size) { + if (DisableScan) + return; + // If our previous scan pointer is inside the buffer, assume we already // scanned those bytes. This depends on raw_ostream to not change our buffer // in unexpected ways. diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 8eb53e440459..807071a7b9a1 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -541,11 +541,6 @@ int main(int argc, char **argv) { std::unique_ptr MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); auto FOut = std::make_unique(*OS); - // FIXME: Workaround for bug in formatted_raw_ostream. Color escape codes - // are (incorrectly) written directly to the unbuffered raw_ostream wrapped - // by the formatted_raw_ostream. - if (Action == AC_CDisassemble) - FOut->SetUnbuffered(); Str.reset( TheTarget->createAsmStreamer(Ctx, std::move(FOut), /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 78cf67b1e630..9b65ea5a99e4 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2115,13 +2115,6 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj, formatted_raw_ostream FOS(outs()); - // FIXME: Workaround for bug in formatted_raw_ostream. Color escape codes - // are (incorrectly) written directly to the unbuffered raw_ostream - // wrapped by the formatted_raw_ostream. - if (DisassemblyColor == ColorOutput::Enable || - DisassemblyColor == ColorOutput::Auto) - FOS.SetUnbuffered(); - std::unordered_map AllLabels; std::unordered_map> BBAddrMapLabels; if (SymbolizeOperands) { -- GitLab From a495cfbf7d544ed2624e8a54f14129fa7824eee4 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Thu, 28 Mar 2024 12:42:02 +0100 Subject: [PATCH 183/541] [IR][NFC] Cleanup CmpInst signatures / code docs (#86441) Change param names to recommended upper case format for static methods in CmpInst for consistency Implement suggestion from @dtcxzyw. cc @dtcxzyw @tschuett --- llvm/include/llvm/IR/InstrTypes.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index 3a30e935849b..e4e5fa15c399 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1032,7 +1032,7 @@ public: /// the two operands. Insert the instruction into a BasicBlock right before /// the specified instruction. /// Create a CmpInst - static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2, + static CmpInst *Create(OtherOps Op, Predicate Pred, Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore); /// Construct a compare instruction, given the opcode, the predicate and @@ -1040,23 +1040,23 @@ public: /// instruction into a BasicBlock right before the specified instruction. /// The specified Instruction is allowed to be a dereferenced end iterator. /// Create a CmpInst - static CmpInst *Create(OtherOps Op, - Predicate predicate, Value *S1, - Value *S2, const Twine &Name = "", + static CmpInst *Create(OtherOps Op, Predicate Pred, Value *S1, Value *S2, + const Twine &Name = "", Instruction *InsertBefore = nullptr); /// Construct a compare instruction, given the opcode, the predicate and the /// two operands. Also automatically insert this instruction to the end of /// the BasicBlock specified. /// Create a CmpInst - static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1, - Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); + static CmpInst *Create(OtherOps Op, Predicate Pred, Value *S1, Value *S2, + const Twine &Name, BasicBlock *InsertAtEnd); /// Construct a compare instruction, given the opcode, the predicate, /// the two operands and the instruction to copy the flags from. Optionally /// (if InstBefore is specified) insert the instruction into a BasicBlock /// right before the specified instruction. The specified Instruction is - /// allowed to be a dereferenced end iterator. Create a CmpInst + /// allowed to be a dereferenced end iterator. + /// Create a CmpInst static CmpInst *CreateWithCopiedFlags(OtherOps Op, Predicate Pred, Value *S1, Value *S2, const Instruction *FlagsSource, -- GitLab From 9d61f7ea660bc4087763e679a7f2b87c50cca108 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Thu, 28 Mar 2024 12:42:44 +0100 Subject: [PATCH 184/541] [flang] Remove duplicate call to va_end() (#86865) Fixes #86825 --- flang/runtime/io-error.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/flang/runtime/io-error.cpp b/flang/runtime/io-error.cpp index 02f237f05bea..b006b82f6224 100644 --- a/flang/runtime/io-error.cpp +++ b/flang/runtime/io-error.cpp @@ -56,9 +56,6 @@ void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) { #endif ioMsg_ = SaveDefaultCharacter( buffer, Fortran::runtime::strlen(buffer) + 1, *this); -#if !defined(RT_DEVICE_COMPILATION) - va_end(ap); -#endif } } return; -- GitLab From daa755ba7b7fe11e078f1e6f43d446234023f859 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 28 Mar 2024 06:49:15 -0500 Subject: [PATCH 185/541] [libc] Disable testing for NVPTX debug builds (#86856) Summary: Debug builds don't optimize out certain parts of the code that end up making the GPU backend crash. This results in regular builds not being successful just to build the testing objects. Disable them for now in debug mode. --- libc/cmake/modules/prepare_libc_gpu_build.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libc/cmake/modules/prepare_libc_gpu_build.cmake b/libc/cmake/modules/prepare_libc_gpu_build.cmake index bea6bb016491..20aca16990fc 100644 --- a/libc/cmake/modules/prepare_libc_gpu_build.cmake +++ b/libc/cmake/modules/prepare_libc_gpu_build.cmake @@ -93,6 +93,11 @@ else() endif() set(LIBC_GPU_TARGET_ARCHITECTURE "${gpu_test_architecture}") +# The NVPTX backend cannot currently handle objects created in debug mode. +if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX AND CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LIBC_GPU_TESTS_DISABLED TRUE) +endif() + # Identify the GPU loader utility used to run tests. set(LIBC_GPU_LOADER_EXECUTABLE "" CACHE STRING "Executable for the GPU loader.") if(LIBC_GPU_LOADER_EXECUTABLE) -- GitLab From 896037c75ace929327e5b0bf5832157f9d81e6e7 Mon Sep 17 00:00:00 2001 From: Haohai Wen Date: Thu, 28 Mar 2024 20:07:15 +0800 Subject: [PATCH 186/541] [LoopRotate] Set loop back edge weight to not less than exit weight (#86496) Branch weight from sample-based PGO may be not inaccurate due to sampling. If the loop body must be executed, then origin loop back edge weight must be not less than exit weight. --- llvm/lib/Transforms/Utils/LoopRotationUtils.cpp | 10 ++++++++++ .../Transforms/LoopRotate/update-branch-weights.ll | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp index bc6711711371..0f55af3b6edd 100644 --- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -347,9 +347,19 @@ static void updateBranchWeights(BranchInst &PreHeaderBI, BranchInst &LoopBI, // probabilities as if there are only 0-trip and 1-trip cases. ExitWeight0 = OrigLoopExitWeight - OrigLoopBackedgeWeight; } + } else { + // Theoretically, if the loop body must be executed at least once, the + // backedge count must be not less than exit count. However the branch + // weight collected by sampling-based PGO may be not very accurate due to + // sampling. Therefore this workaround is required here to avoid underflow + // of unsigned in following update of branch weight. + if (OrigLoopExitWeight > OrigLoopBackedgeWeight) + OrigLoopBackedgeWeight = OrigLoopExitWeight; } + assert(OrigLoopExitWeight >= ExitWeight0 && "Bad branch weight"); ExitWeight1 = OrigLoopExitWeight - ExitWeight0; EnterWeight = ExitWeight1; + assert(OrigLoopBackedgeWeight >= EnterWeight && "Bad branch weight"); LoopBackWeight = OrigLoopBackedgeWeight - EnterWeight; } else if (OrigLoopExitWeight == 0) { if (OrigLoopBackedgeWeight == 0) { diff --git a/llvm/test/Transforms/LoopRotate/update-branch-weights.ll b/llvm/test/Transforms/LoopRotate/update-branch-weights.ll index acb2038d17bb..9a1f36ec5ff2 100644 --- a/llvm/test/Transforms/LoopRotate/update-branch-weights.ll +++ b/llvm/test/Transforms/LoopRotate/update-branch-weights.ll @@ -240,7 +240,7 @@ loop_exit: ; BFI_AFTER-LABEL: block-frequency-info: func6_inaccurate_branch_weight ; BFI_AFTER: - entry: {{.*}} count = 1024 -; BFI_AFTER: - loop_body: {{.*}} count = 4294967296 +; BFI_AFTER: - loop_body: {{.*}} count = 1024 ; BFI_AFTER: - loop_exit: {{.*}} count = 1024 ; IR-LABEL: define void @func6_inaccurate_branch_weight( @@ -292,4 +292,4 @@ loop_exit: ; IR: [[PROF_FUNC3_0]] = !{!"branch_weights", i32 0, i32 1} ; IR: [[PROF_FUNC4_0]] = !{!"branch_weights", i32 1, i32 0} ; IR: [[PROF_FUNC5_0]] = !{!"branch_weights", i32 0, i32 0} -; IR: [[PROF_FUNC6_0]] = !{!"branch_weights", i32 -1, i32 1024} +; IR: [[PROF_FUNC6_0]] = !{!"branch_weights", i32 0, i32 1024} -- GitLab From fb8cccf88c5d04f36148ff336b6dc7c25746b1de Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 28 Mar 2024 13:07:58 +0100 Subject: [PATCH 187/541] [AST] Print the "aggregate" for aggregate deduction guide decl. (#84018) I found this is useful for debugging purpose to identify different kind of deduction guide decl. --- clang/include/clang/AST/TextNodeDumper.h | 1 + clang/lib/AST/TextNodeDumper.cpp | 13 +++++++++++++ clang/test/SemaTemplate/deduction-guide.cpp | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index de67f0b57148..efb5bfe7f83d 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -352,6 +352,7 @@ public: void VisitEnumConstantDecl(const EnumConstantDecl *D); void VisitIndirectFieldDecl(const IndirectFieldDecl *D); void VisitFunctionDecl(const FunctionDecl *D); + void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *D); void VisitFieldDecl(const FieldDecl *D); void VisitVarDecl(const VarDecl *D); void VisitBindingDecl(const BindingDecl *D); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index b683eb1edd8f..413e452146bd 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1990,6 +1990,19 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { } } +void TextNodeDumper::VisitCXXDeductionGuideDecl( + const CXXDeductionGuideDecl *D) { + VisitFunctionDecl(D); + switch (D->getDeductionCandidateKind()) { + case DeductionCandidate::Normal: + case DeductionCandidate::Copy: + return; + case DeductionCandidate::Aggregate: + OS << " aggregate "; + break; + } +} + void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl( const LifetimeExtendedTemporaryDecl *D) { OS << " extended by "; diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 16c7083df29d..0caef78fedbf 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -239,3 +239,12 @@ F s(0); // CHECK: |-InjectedClassNameType {{.*}} 'F<>' dependent // CHECK: | `-CXXRecord {{.*}} 'F' // CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent depth 0 index 1 + +template +struct G { T t; }; + +G g = {1}; +// CHECK-LABEL: Dumping : +// CHECK: FunctionTemplateDecl +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (T) -> G' aggregate +// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (int) -> G' implicit_instantiation aggregate -- GitLab From a042fcbe45d1ae64acc5d818db90e26e16e1aab3 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 28 Mar 2024 13:10:02 +0100 Subject: [PATCH 188/541] [clang] Bailout when the substitution of template parameter mapping is invalid. (#86869) Fixes #86757 We missed to handle the invalid case when substituting into the parameter mapping of an constraint during normalization. The constructor of `InstantiatingTemplate` will bail out (no `CodeSynthesisContext` will be added to the instantiation stack) if there was a fatal error, consequently we should stop doing any further template instantiations. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaConcept.cpp | 2 ++ clang/test/SemaTemplate/concepts-GH86757.cpp | 13 +++++++++++++ 3 files changed, 16 insertions(+) create mode 100644 clang/test/SemaTemplate/concepts-GH86757.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ccc399d36dbb..232de0d7d8bb 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -458,6 +458,7 @@ Bug Fixes to C++ Support - Fix an issue where a namespace alias could be defined using a qualified name (all name components following the first `::` were ignored). - Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757). +- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index b6c4d3d540ef..a2d8ba9a96d7 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1281,6 +1281,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N, S, InstLocBegin, Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, {InstLocBegin, InstLocEnd}); + if (Inst.isInvalid()) + return true; if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) return true; diff --git a/clang/test/SemaTemplate/concepts-GH86757.cpp b/clang/test/SemaTemplate/concepts-GH86757.cpp new file mode 100644 index 000000000000..3122381b2035 --- /dev/null +++ b/clang/test/SemaTemplate/concepts-GH86757.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++20 -Wfatal-errors -verify %s + +template int a; +template concept c = a; +template concept e = c<>; + +// must be a fatal error to trigger the crash +undefined; // expected-error {{a type specifier is required for all declarations}} + +template concept g = e; +template struct h +template +struct h; -- GitLab From 4ddd4ed7fe15a356dace649e18492dd01071f475 Mon Sep 17 00:00:00 2001 From: Zaara Syeda Date: Thu, 28 Mar 2024 08:37:25 -0400 Subject: [PATCH 189/541] [AIX][TOC] -mtocdata/-mno-tocdata fix non deterministic iteration order (#86840) Failure with testcase toc-conf.c observed when building with LLVM_REVERSE_ITERATION=ON. Changing from using llvm::StringSet to std::set to ensure iteration order is deterministic. Note: the functionality of the feature does not require a specific iteration order, however, this will allow testing to be consistent. From llvm docs: The advantages of std::set are that its iterators are stable (deleting or inserting an element from the set does not affect iterators or pointers to other elements) and that iteration over the set is guaranteed to be in sorted order. --- clang/lib/Driver/ToolChains/AIX.cpp | 6 +++--- clang/test/Driver/toc-conf.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 6e089903a315..7a62b0f9aec4 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -471,7 +471,7 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args, // the global setting of tocdata in TOCDataGloballyinEffect. // Those that have the opposite setting to TOCDataGloballyinEffect, are added // to ExplicitlySpecifiedGlobals. - llvm::StringSet<> ExplicitlySpecifiedGlobals; + std::set ExplicitlySpecifiedGlobals; for (const auto Arg : Args.filtered(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ)) { TOCDataSetting ArgTocDataSetting = @@ -486,7 +486,7 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args, ExplicitlySpecifiedGlobals.erase(Val); } - auto buildExceptionList = [](const llvm::StringSet<> &ExplicitValues, + auto buildExceptionList = [](const std::set &ExplicitValues, const char *OptionSpelling) { std::string Option(OptionSpelling); bool IsFirst = true; @@ -495,7 +495,7 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args, Option += ","; IsFirst = false; - Option += E.first(); + Option += E.str(); } return Option; }; diff --git a/clang/test/Driver/toc-conf.c b/clang/test/Driver/toc-conf.c index 80d92ee1a90b..7b2d5122ebc6 100644 --- a/clang/test/Driver/toc-conf.c +++ b/clang/test/Driver/toc-conf.c @@ -23,7 +23,7 @@ void func() { // CHECK-CONF1-NOT: warning: // CHECK-CONF1: "-cc1"{{.*}}" "-mno-tocdata" -// CHECK-CONF1: "-mtocdata=g2,g1" +// CHECK-CONF1: "-mtocdata=g1,g2" // CHECK-CONF2-NOT: warning: // CHECK-CONF2: "-cc1"{{.*}}" "-mtocdata" -- GitLab From 79199753fd6c39aac881b9556614c5db2775dc85 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 28 Mar 2024 07:46:01 -0500 Subject: [PATCH 190/541] [flang][OpenMP] Make several function local to OpenMP.cpp, NFC (#86726) There were several functions, mostly reduction-related, that were only called from OpenMP.cpp. Remove them from OpenMP.h, and make them local in OpenMP.cpp: - genOpenMPReduction - findReductionChain - getConvertFromReductionOp - updateReduction - removeStoreOp Also, move the function bodies out of the "public" section. --- flang/include/flang/Lower/OpenMP.h | 12 - flang/lib/Lower/OpenMP/OpenMP.cpp | 417 ++++++++++++++--------------- 2 files changed, 207 insertions(+), 222 deletions(-) diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h index 3b22a652d1fc..6e150ef4e8e8 100644 --- a/flang/include/flang/Lower/OpenMP.h +++ b/flang/include/flang/Lower/OpenMP.h @@ -19,7 +19,6 @@ #include namespace mlir { -class Value; class Operation; class Location; namespace omp { @@ -30,7 +29,6 @@ enum class DeclareTargetCaptureClause : uint32_t; namespace fir { class FirOpBuilder; -class ConvertOp; } // namespace fir namespace Fortran { @@ -84,16 +82,6 @@ void genOpenMPSymbolProperties(AbstractConverter &converter, int64_t getCollapseValue(const Fortran::parser::OmpClauseList &clauseList); void genThreadprivateOp(AbstractConverter &, const pft::Variable &); void genDeclareTargetIntGlobal(AbstractConverter &, const pft::Variable &); -void genOpenMPReduction(AbstractConverter &, - Fortran::semantics::SemanticsContext &, - const Fortran::parser::OmpClauseList &clauseList); - -mlir::Operation *findReductionChain(mlir::Value, mlir::Value * = nullptr); -fir::ConvertOp getConvertFromReductionOp(mlir::Operation *, mlir::Value); -void updateReduction(mlir::Operation *, fir::FirOpBuilder &, mlir::Value, - mlir::Value, fir::ConvertOp * = nullptr); -void removeStoreOp(mlir::Operation *, mlir::Value); - bool isOpenMPTargetConstruct(const parser::OpenMPConstruct &); bool isOpenMPDeviceDeclareTarget(Fortran::lower::AbstractConverter &, Fortran::semantics::SemanticsContext &, diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 5defffd738b4..340921c86724 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -237,6 +237,213 @@ createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter, return storeOp; } +static mlir::Operation * +findReductionChain(mlir::Value loadVal, mlir::Value *reductionVal = nullptr) { + for (mlir::OpOperand &loadOperand : loadVal.getUses()) { + if (mlir::Operation *reductionOp = loadOperand.getOwner()) { + if (auto convertOp = mlir::dyn_cast(reductionOp)) { + for (mlir::OpOperand &convertOperand : convertOp.getRes().getUses()) { + if (mlir::Operation *reductionOp = convertOperand.getOwner()) + return reductionOp; + } + } + for (mlir::OpOperand &reductionOperand : reductionOp->getUses()) { + if (auto store = + mlir::dyn_cast(reductionOperand.getOwner())) { + if (store.getMemref() == *reductionVal) { + store.erase(); + return reductionOp; + } + } + if (auto assign = + mlir::dyn_cast(reductionOperand.getOwner())) { + if (assign.getLhs() == *reductionVal) { + assign.erase(); + return reductionOp; + } + } + } + } + } + return nullptr; +} + +// for a logical operator 'op' reduction X = X op Y +// This function returns the operation responsible for converting Y from +// fir.logical<4> to i1 +static fir::ConvertOp getConvertFromReductionOp(mlir::Operation *reductionOp, + mlir::Value loadVal) { + for (mlir::Value reductionOperand : reductionOp->getOperands()) { + if (auto convertOp = + mlir::dyn_cast(reductionOperand.getDefiningOp())) { + if (convertOp.getOperand() == loadVal) + continue; + return convertOp; + } + } + return nullptr; +} + +static void updateReduction(mlir::Operation *op, + fir::FirOpBuilder &firOpBuilder, + mlir::Value loadVal, mlir::Value reductionVal, + fir::ConvertOp *convertOp = nullptr) { + mlir::OpBuilder::InsertPoint insertPtDel = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPoint(op); + + mlir::Value reductionOp; + if (convertOp) + reductionOp = convertOp->getOperand(); + else if (op->getOperand(0) == loadVal) + reductionOp = op->getOperand(1); + else + reductionOp = op->getOperand(0); + + firOpBuilder.create(op->getLoc(), reductionOp, + reductionVal); + firOpBuilder.restoreInsertionPoint(insertPtDel); +} + +static void removeStoreOp(mlir::Operation *reductionOp, mlir::Value symVal) { + for (mlir::Operation *reductionOpUse : reductionOp->getUsers()) { + if (auto convertReduction = + mlir::dyn_cast(reductionOpUse)) { + for (mlir::Operation *convertReductionUse : + convertReduction.getRes().getUsers()) { + if (auto storeOp = mlir::dyn_cast(convertReductionUse)) { + if (storeOp.getMemref() == symVal) + storeOp.erase(); + } + if (auto assignOp = + mlir::dyn_cast(convertReductionUse)) { + if (assignOp.getLhs() == symVal) + assignOp.erase(); + } + } + } + } +} + +// Generate an OpenMP reduction operation. +// TODO: Currently assumes it is either an integer addition/multiplication +// reduction, or a logical and reduction. Generalize this for various reduction +// operation types. +// TODO: Generate the reduction operation during lowering instead of creating +// and removing operations since this is not a robust approach. Also, removing +// ops in the builder (instead of a rewriter) is probably not the best approach. +static void +genOpenMPReduction(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + const Fortran::parser::OmpClauseList &clauseList) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + + List clauses{makeClauses(clauseList, semaCtx)}; + + for (const Clause &clause : clauses) { + if (const auto &reductionClause = + std::get_if(&clause.u)) { + const auto &redOperatorList{ + std::get( + reductionClause->t)}; + assert(redOperatorList.size() == 1 && "Expecting single operator"); + const auto &redOperator = redOperatorList.front(); + const auto &objects{std::get(reductionClause->t)}; + if (const auto *reductionOp = + std::get_if(&redOperator.u)) { + const auto &intrinsicOp{ + std::get( + reductionOp->u)}; + + switch (intrinsicOp) { + case clause::DefinedOperator::IntrinsicOperator::Add: + case clause::DefinedOperator::IntrinsicOperator::Multiply: + case clause::DefinedOperator::IntrinsicOperator::AND: + case clause::DefinedOperator::IntrinsicOperator::EQV: + case clause::DefinedOperator::IntrinsicOperator::OR: + case clause::DefinedOperator::IntrinsicOperator::NEQV: + break; + default: + continue; + } + for (const Object &object : objects) { + if (const Fortran::semantics::Symbol *symbol = object.id()) { + mlir::Value reductionVal = converter.getSymbolAddress(*symbol); + if (auto declOp = reductionVal.getDefiningOp()) + reductionVal = declOp.getBase(); + mlir::Type reductionType = + reductionVal.getType().cast().getEleTy(); + if (!reductionType.isa()) { + if (!reductionType.isIntOrIndexOrFloat()) + continue; + } + for (mlir::OpOperand &reductionValUse : reductionVal.getUses()) { + if (auto loadOp = + mlir::dyn_cast(reductionValUse.getOwner())) { + mlir::Value loadVal = loadOp.getRes(); + if (reductionType.isa()) { + mlir::Operation *reductionOp = findReductionChain(loadVal); + fir::ConvertOp convertOp = + getConvertFromReductionOp(reductionOp, loadVal); + updateReduction(reductionOp, firOpBuilder, loadVal, + reductionVal, &convertOp); + removeStoreOp(reductionOp, reductionVal); + } else if (mlir::Operation *reductionOp = + findReductionChain(loadVal, &reductionVal)) { + updateReduction(reductionOp, firOpBuilder, loadVal, + reductionVal); + } + } + } + } + } + } else if (const auto *reductionIntrinsic = + std::get_if(&redOperator.u)) { + if (!ReductionProcessor::supportedIntrinsicProcReduction( + *reductionIntrinsic)) + continue; + ReductionProcessor::ReductionIdentifier redId = + ReductionProcessor::getReductionType(*reductionIntrinsic); + for (const Object &object : objects) { + if (const Fortran::semantics::Symbol *symbol = object.id()) { + mlir::Value reductionVal = converter.getSymbolAddress(*symbol); + if (auto declOp = reductionVal.getDefiningOp()) + reductionVal = declOp.getBase(); + for (const mlir::OpOperand &reductionValUse : + reductionVal.getUses()) { + if (auto loadOp = + mlir::dyn_cast(reductionValUse.getOwner())) { + mlir::Value loadVal = loadOp.getRes(); + // Max is lowered as a compare -> select. + // Match the pattern here. + mlir::Operation *reductionOp = + findReductionChain(loadVal, &reductionVal); + if (reductionOp == nullptr) + continue; + + if (redId == ReductionProcessor::ReductionIdentifier::MAX || + redId == ReductionProcessor::ReductionIdentifier::MIN) { + assert(mlir::isa(reductionOp) && + "Selection Op not found in reduction intrinsic"); + mlir::Operation *compareOp = + getCompareFromReductionOp(reductionOp, loadVal); + updateReduction(compareOp, firOpBuilder, loadVal, + reductionVal); + } + if (redId == ReductionProcessor::ReductionIdentifier::IOR || + redId == ReductionProcessor::ReductionIdentifier::IEOR || + redId == ReductionProcessor::ReductionIdentifier::IAND) { + updateReduction(reductionOp, firOpBuilder, loadVal, + reductionVal); + } + } + } + } + } + } + } + } +} + struct OpWithBodyGenInfo { /// A type for a code-gen callback function. This takes as argument the op for /// which the code is being generated and returns the arguments of the op's @@ -2339,216 +2546,6 @@ void Fortran::lower::genDeclareTargetIntGlobal( } } -// Generate an OpenMP reduction operation. -// TODO: Currently assumes it is either an integer addition/multiplication -// reduction, or a logical and reduction. Generalize this for various reduction -// operation types. -// TODO: Generate the reduction operation during lowering instead of creating -// and removing operations since this is not a robust approach. Also, removing -// ops in the builder (instead of a rewriter) is probably not the best approach. -void Fortran::lower::genOpenMPReduction( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - const Fortran::parser::OmpClauseList &clauseList) { - fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - - List clauses{makeClauses(clauseList, semaCtx)}; - - for (const Clause &clause : clauses) { - if (const auto &reductionClause = - std::get_if(&clause.u)) { - const auto &redOperatorList{ - std::get( - reductionClause->t)}; - assert(redOperatorList.size() == 1 && "Expecting single operator"); - const auto &redOperator = redOperatorList.front(); - const auto &objects{std::get(reductionClause->t)}; - if (const auto *reductionOp = - std::get_if(&redOperator.u)) { - const auto &intrinsicOp{ - std::get( - reductionOp->u)}; - - switch (intrinsicOp) { - case clause::DefinedOperator::IntrinsicOperator::Add: - case clause::DefinedOperator::IntrinsicOperator::Multiply: - case clause::DefinedOperator::IntrinsicOperator::AND: - case clause::DefinedOperator::IntrinsicOperator::EQV: - case clause::DefinedOperator::IntrinsicOperator::OR: - case clause::DefinedOperator::IntrinsicOperator::NEQV: - break; - default: - continue; - } - for (const Object &object : objects) { - if (const Fortran::semantics::Symbol *symbol = object.id()) { - mlir::Value reductionVal = converter.getSymbolAddress(*symbol); - if (auto declOp = reductionVal.getDefiningOp()) - reductionVal = declOp.getBase(); - mlir::Type reductionType = - reductionVal.getType().cast().getEleTy(); - if (!reductionType.isa()) { - if (!reductionType.isIntOrIndexOrFloat()) - continue; - } - for (mlir::OpOperand &reductionValUse : reductionVal.getUses()) { - if (auto loadOp = - mlir::dyn_cast(reductionValUse.getOwner())) { - mlir::Value loadVal = loadOp.getRes(); - if (reductionType.isa()) { - mlir::Operation *reductionOp = findReductionChain(loadVal); - fir::ConvertOp convertOp = - getConvertFromReductionOp(reductionOp, loadVal); - updateReduction(reductionOp, firOpBuilder, loadVal, - reductionVal, &convertOp); - removeStoreOp(reductionOp, reductionVal); - } else if (mlir::Operation *reductionOp = - findReductionChain(loadVal, &reductionVal)) { - updateReduction(reductionOp, firOpBuilder, loadVal, - reductionVal); - } - } - } - } - } - } else if (const auto *reductionIntrinsic = - std::get_if(&redOperator.u)) { - if (!ReductionProcessor::supportedIntrinsicProcReduction( - *reductionIntrinsic)) - continue; - ReductionProcessor::ReductionIdentifier redId = - ReductionProcessor::getReductionType(*reductionIntrinsic); - for (const Object &object : objects) { - if (const Fortran::semantics::Symbol *symbol = object.id()) { - mlir::Value reductionVal = converter.getSymbolAddress(*symbol); - if (auto declOp = reductionVal.getDefiningOp()) - reductionVal = declOp.getBase(); - for (const mlir::OpOperand &reductionValUse : - reductionVal.getUses()) { - if (auto loadOp = - mlir::dyn_cast(reductionValUse.getOwner())) { - mlir::Value loadVal = loadOp.getRes(); - // Max is lowered as a compare -> select. - // Match the pattern here. - mlir::Operation *reductionOp = - findReductionChain(loadVal, &reductionVal); - if (reductionOp == nullptr) - continue; - - if (redId == ReductionProcessor::ReductionIdentifier::MAX || - redId == ReductionProcessor::ReductionIdentifier::MIN) { - assert(mlir::isa(reductionOp) && - "Selection Op not found in reduction intrinsic"); - mlir::Operation *compareOp = - getCompareFromReductionOp(reductionOp, loadVal); - updateReduction(compareOp, firOpBuilder, loadVal, - reductionVal); - } - if (redId == ReductionProcessor::ReductionIdentifier::IOR || - redId == ReductionProcessor::ReductionIdentifier::IEOR || - redId == ReductionProcessor::ReductionIdentifier::IAND) { - updateReduction(reductionOp, firOpBuilder, loadVal, - reductionVal); - } - } - } - } - } - } - } - } -} - -mlir::Operation *Fortran::lower::findReductionChain(mlir::Value loadVal, - mlir::Value *reductionVal) { - for (mlir::OpOperand &loadOperand : loadVal.getUses()) { - if (mlir::Operation *reductionOp = loadOperand.getOwner()) { - if (auto convertOp = mlir::dyn_cast(reductionOp)) { - for (mlir::OpOperand &convertOperand : convertOp.getRes().getUses()) { - if (mlir::Operation *reductionOp = convertOperand.getOwner()) - return reductionOp; - } - } - for (mlir::OpOperand &reductionOperand : reductionOp->getUses()) { - if (auto store = - mlir::dyn_cast(reductionOperand.getOwner())) { - if (store.getMemref() == *reductionVal) { - store.erase(); - return reductionOp; - } - } - if (auto assign = - mlir::dyn_cast(reductionOperand.getOwner())) { - if (assign.getLhs() == *reductionVal) { - assign.erase(); - return reductionOp; - } - } - } - } - } - return nullptr; -} - -// for a logical operator 'op' reduction X = X op Y -// This function returns the operation responsible for converting Y from -// fir.logical<4> to i1 -fir::ConvertOp -Fortran::lower::getConvertFromReductionOp(mlir::Operation *reductionOp, - mlir::Value loadVal) { - for (mlir::Value reductionOperand : reductionOp->getOperands()) { - if (auto convertOp = - mlir::dyn_cast(reductionOperand.getDefiningOp())) { - if (convertOp.getOperand() == loadVal) - continue; - return convertOp; - } - } - return nullptr; -} - -void Fortran::lower::updateReduction(mlir::Operation *op, - fir::FirOpBuilder &firOpBuilder, - mlir::Value loadVal, - mlir::Value reductionVal, - fir::ConvertOp *convertOp) { - mlir::OpBuilder::InsertPoint insertPtDel = firOpBuilder.saveInsertionPoint(); - firOpBuilder.setInsertionPoint(op); - - mlir::Value reductionOp; - if (convertOp) - reductionOp = convertOp->getOperand(); - else if (op->getOperand(0) == loadVal) - reductionOp = op->getOperand(1); - else - reductionOp = op->getOperand(0); - - firOpBuilder.create(op->getLoc(), reductionOp, - reductionVal); - firOpBuilder.restoreInsertionPoint(insertPtDel); -} - -void Fortran::lower::removeStoreOp(mlir::Operation *reductionOp, - mlir::Value symVal) { - for (mlir::Operation *reductionOpUse : reductionOp->getUsers()) { - if (auto convertReduction = - mlir::dyn_cast(reductionOpUse)) { - for (mlir::Operation *convertReductionUse : - convertReduction.getRes().getUsers()) { - if (auto storeOp = mlir::dyn_cast(convertReductionUse)) { - if (storeOp.getMemref() == symVal) - storeOp.erase(); - } - if (auto assignOp = - mlir::dyn_cast(convertReductionUse)) { - if (assignOp.getLhs() == symVal) - assignOp.erase(); - } - } - } - } -} - bool Fortran::lower::isOpenMPTargetConstruct( const Fortran::parser::OpenMPConstruct &omp) { llvm::omp::Directive dir = llvm::omp::Directive::OMPD_unknown; -- GitLab From 56a10a3c7930164a875db7c34da8c2a8b8abfbee Mon Sep 17 00:00:00 2001 From: VitaNuo <115406782+VitaNuo@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:48:09 +0100 Subject: [PATCH 191/541] =?UTF-8?q?[clangd][trace]=20Fix=20comment=20to=20?= =?UTF-8?q?mention=20that=20trace=20spans=20are=20measured=20=E2=80=A6=20(?= =?UTF-8?q?#86938)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …in milliseconds rather than seconds. --- clang-tools-extra/clangd/support/Trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/support/Trace.h b/clang-tools-extra/clangd/support/Trace.h index 1bfc75b874d8..36c3745a41e9 100644 --- a/clang-tools-extra/clangd/support/Trace.h +++ b/clang-tools-extra/clangd/support/Trace.h @@ -143,8 +143,8 @@ bool enabled(); class Span { public: Span(llvm::Twine Name); - /// Records span's duration in seconds to \p LatencyMetric with \p Name as the - /// label. + /// Records span's duration in milliseconds to \p LatencyMetric with \p Name + /// as the label. Span(llvm::Twine Name, const Metric &LatencyMetric); ~Span(); -- GitLab From e8e80d07c867cadcfd82741693a04b2913904956 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 28 Mar 2024 07:52:47 -0500 Subject: [PATCH 192/541] [OpenMP] Apply post-commit review comments in PR86289, NFC (#86828) Fix include guard name, fix typo, add comments with OpenMP spec sections. --- flang/lib/Lower/OpenMP/Clauses.cpp | 2 +- llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 151 +++++++++++++++++++- 2 files changed, 149 insertions(+), 4 deletions(-) diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 853dcd78e266..40da71c8b55f 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -325,7 +325,7 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp, // Absent: missing-in-parser // AcqRel: empty // Acquire: empty -// AdjustArgs: incomplate +// AdjustArgs: incomplete Affinity make(const parser::OmpClause::Affinity &inp, semantics::SemanticsContext &semaCtx) { diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index c48b9169c60e..6ce972adcf0f 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -5,8 +5,41 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#ifndef FORTRAN_LOWER_OPENMP_CLAUSET_H -#define FORTRAN_LOWER_OPENMP_CLAUSET_H +// This file contains template classes that represent OpenMP clauses, as +// described in the OpenMP API specification. +// +// The general structure of any specific clause class is that it is either +// empty, or it consists of a single data member, which can take one of these +// three forms: +// - a value member, named `v`, or +// - a tuple of values, named `t`, or +// - a variant (i.e. union) of values, named `u`. +// To assist with generic visit algorithms, classes define one of the following +// traits: +// - EmptyTrait: the class has no data members. +// - WrapperTrait: the class has a single member `v` +// - TupleTrait: the class has a tuple member `t` +// - UnionTrait the class has a varuant member `u` +// - IncompleteTrait: the class is a placeholder class that is currently empty, +// but will be completed at a later time. +// Note: This structure follows the one used in flang parser. +// +// The types used in the class definitions follow the names used in the spec +// (there are a few exceptions to this). For example, given +// Clause `foo` +// - foo-modifier : description... +// - list : list of variables +// the corresponding class would be +// template <...> +// struct FooT { +// using FooModifier = type that can represent the modifier +// using List = ListT>; +// using TupleTrait = std::true_type; +// std::tuple, List> t; +// }; +//===----------------------------------------------------------------------===// +#ifndef LLVM_FRONTEND_OPENMP_CLAUSET_H +#define LLVM_FRONTEND_OPENMP_CLAUSET_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -161,6 +194,7 @@ struct DefinedOperatorT { std::variant u; }; +// V5.2: [3.2.6] `iterator` modifier template // struct RangeT { // range-specification: begin : end[: step] @@ -168,6 +202,7 @@ struct RangeT { std::tuple t; }; +// V5.2: [3.2.6] `iterator` modifier template // struct IteratorSpecifierT { // iterators-specifier: [ iterator-type ] identifier = range-specification @@ -183,6 +218,7 @@ struct IteratorSpecifierT { // is allowed. If the mapper list contains a single element, it applies to // all objects in the clause, otherwise there should be as many mappers as // there are objects. +// V5.2: [5.8.2] Mapper identifiers and `mapper` modifiers template // struct MapperT { using MapperIdentifier = ObjectT; @@ -190,8 +226,11 @@ struct MapperT { MapperIdentifier v; }; +// V5.2: [15.8.1] `memory-order` clauses +// When used as arguments for other clauses, e.g. `fail`. ENUM(MemoryOrder, AcqRel, Acquire, Relaxed, Release, SeqCst); ENUM(MotionExpectation, Present); +// V5.2: [15.9.1] `task-dependence-type` modifier ENUM(TaskDependenceType, In, Out, Inout, Mutexinoutset, Inoutset, Depobj); template // @@ -246,6 +285,7 @@ ListT makeList(ContainerTy &&container, FunctionTy &&func) { } namespace clause { +// V5.2: [8.3.1] `assumption` clauses template // struct AbsentT { using List = ListT; @@ -253,21 +293,25 @@ struct AbsentT { List v; }; +// V5.2: [15.8.1] `memory-order` clauses template // struct AcqRelT { using EmptyTrait = std::true_type; }; +// V5.2: [15.8.1] `memory-order` clauses template // struct AcquireT { using EmptyTrait = std::true_type; }; +// V5.2: [7.5.2] `adjust_args` clause template // struct AdjustArgsT { using IncompleteTrait = std::true_type; }; +// V5.2: [12.5.1] `affinity` clause template // struct AffinityT { using Iterator = type::IteratorT; @@ -277,6 +321,7 @@ struct AffinityT { std::tuple t; }; +// V5.2: [6.3] `align` clause template // struct AlignT { using Alignment = E; @@ -285,6 +330,7 @@ struct AlignT { Alignment v; }; +// V5.2: [5.11] `aligned` clause template // struct AlignedT { using Alignment = E; @@ -297,6 +343,7 @@ struct AlignedT { template // struct AllocatorT; +// V5.2: [6.6] `allocate` clause template // struct AllocateT { using AllocatorSimpleModifier = E; @@ -310,6 +357,7 @@ struct AllocateT { t; }; +// V5.2: [6.4] `allocator` clause template // struct AllocatorT { using Allocator = E; @@ -317,11 +365,13 @@ struct AllocatorT { Allocator v; }; +// V5.2: [7.5.3] `append_args` clause template // struct AppendArgsT { using IncompleteTrait = std::true_type; }; +// V5.2: [8.1] `at` clause template // struct AtT { ENUM(ActionTime, Compilation, Execution); @@ -329,6 +379,7 @@ struct AtT { ActionTime v; }; +// V5.2: [8.2.1] `requirement` clauses template // struct AtomicDefaultMemOrderT { using MemoryOrder = type::MemoryOrder; @@ -336,6 +387,7 @@ struct AtomicDefaultMemOrderT { MemoryOrder v; // Name not provided in spec }; +// V5.2: [11.7.1] `bind` clause template // struct BindT { ENUM(Binding, Teams, Parallel, Thread); @@ -343,11 +395,13 @@ struct BindT { Binding v; }; +// V5.2: [15.8.3] `extended-atomic` clauses template // struct CaptureT { using EmptyTrait = std::true_type; }; +// V5.2: [4.4.3] `collapse` clause template // struct CollapseT { using N = E; @@ -355,11 +409,13 @@ struct CollapseT { N v; }; +// V5.2: [15.8.3] `extended-atomic` clauses template // struct CompareT { using EmptyTrait = std::true_type; }; +// V5.2: [8.3.1] `assumption` clauses template // struct ContainsT { using List = ListT; @@ -367,6 +423,7 @@ struct ContainsT { List v; }; +// V5.2: [5.7.1] `copyin` clause template // struct CopyinT { using List = ObjectListT; @@ -374,6 +431,7 @@ struct CopyinT { List v; }; +// V5.2: [5.7.2] `copyprivate` clause template // struct CopyprivateT { using List = ObjectListT; @@ -381,6 +439,7 @@ struct CopyprivateT { List v; }; +// V5.2: [5.4.1] `default` clause template // struct DefaultT { ENUM(DataSharingAttribute, Firstprivate, None, Private, Shared); @@ -388,6 +447,7 @@ struct DefaultT { DataSharingAttribute v; }; +// V5.2: [5.8.7] `defaultmap` clause template // struct DefaultmapT { ENUM(ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default, @@ -400,6 +460,7 @@ struct DefaultmapT { template // struct DoacrossT; +// V5.2: [15.9.5] `depend` clause template // struct DependT { using Iterator = type::IteratorT; @@ -417,6 +478,7 @@ struct DependT { std::variant u; // Doacross form is legacy }; +// V5.2: [3.5] `destroy` clause template // struct DestroyT { using DestroyVar = ObjectT; @@ -425,6 +487,7 @@ struct DestroyT { OPT(DestroyVar) v; }; +// V5.2: [12.5.2] `detach` clause template // struct DetachT { using EventHandle = ObjectT; @@ -432,6 +495,7 @@ struct DetachT { EventHandle v; }; +// V5.2: [13.2] `device` clause template // struct DeviceT { using DeviceDescription = E; @@ -440,6 +504,7 @@ struct DeviceT { std::tuple t; }; +// V5.2: [13.1] `device_type` clause template // struct DeviceTypeT { ENUM(DeviceTypeDescription, Any, Host, Nohost); @@ -447,6 +512,7 @@ struct DeviceTypeT { DeviceTypeDescription v; }; +// V5.2: [11.6.1] `dist_schedule` clause template // struct DistScheduleT { ENUM(Kind, Static); @@ -455,6 +521,7 @@ struct DistScheduleT { std::tuple t; }; +// V5.2: [15.9.6] `doacross` clause template // struct DoacrossT { using Vector = ListT>; @@ -464,11 +531,13 @@ struct DoacrossT { std::tuple t; }; +// V5.2: [8.2.1] `requirement` clauses template // struct DynamicAllocatorsT { using EmptyTrait = std::true_type; }; +// V5.2: [5.8.4] `enter` clause template // struct EnterT { using List = ObjectListT; @@ -476,6 +545,7 @@ struct EnterT { List v; }; +// V5.2: [5.6.2] `exclusive` clause template // struct ExclusiveT { using WrapperTrait = std::true_type; @@ -483,6 +553,7 @@ struct ExclusiveT { List v; }; +// V5.2: [15.8.3] `extended-atomic` clauses template // struct FailT { using MemoryOrder = type::MemoryOrder; @@ -490,6 +561,7 @@ struct FailT { MemoryOrder v; }; +// V5.2: [10.5.1] `filter` clause template // struct FilterT { using ThreadNum = E; @@ -497,6 +569,7 @@ struct FilterT { ThreadNum v; }; +// V5.2: [12.3] `final` clause template // struct FinalT { using Finalize = E; @@ -504,6 +577,7 @@ struct FinalT { Finalize v; }; +// V5.2: [5.4.4] `firstprivate` clause template // struct FirstprivateT { using List = ObjectListT; @@ -511,6 +585,7 @@ struct FirstprivateT { List v; }; +// V5.2: [5.9.2] `from` clause template // struct FromT { using LocatorList = ObjectListT; @@ -523,11 +598,13 @@ struct FromT { std::tuple t; }; +// V5.2: [9.2.1] `full` clause template // struct FullT { using EmptyTrait = std::true_type; }; +// V5.2: [12.6.1] `grainsize` clause template // struct GrainsizeT { ENUM(Prescriptiveness, Strict); @@ -536,6 +613,7 @@ struct GrainsizeT { std::tuple t; }; +// V5.2: [5.4.9] `has_device_addr` clause template // struct HasDeviceAddrT { using List = ObjectListT; @@ -543,6 +621,7 @@ struct HasDeviceAddrT { List v; }; +// V5.2: [15.1.2] `hint` clause template // struct HintT { using HintExpr = E; @@ -550,12 +629,14 @@ struct HintT { HintExpr v; }; +// V5.2: [8.3.1] Assumption clauses template // struct HoldsT { using WrapperTrait = std::true_type; E v; // No argument name in spec 5.2 }; +// V5.2: [3.4] `if` clause template // struct IfT { using DirectiveNameModifier = type::DirectiveName; @@ -564,11 +645,13 @@ struct IfT { std::tuple t; }; +// V5.2: [7.7.1] `branch` clauses template // struct InbranchT { using EmptyTrait = std::true_type; }; +// V5.2: [5.6.1] `exclusive` clause template // struct InclusiveT { using List = ObjectListT; @@ -576,6 +659,7 @@ struct InclusiveT { List v; }; +// V5.2: [7.8.3] `indirect` clause template // struct IndirectT { using InvokedByFptr = E; @@ -583,6 +667,7 @@ struct IndirectT { InvokedByFptr v; }; +// V5.2: [14.1.2] `init` clause template // struct InitT { using ForeignRuntimeId = E; @@ -595,6 +680,7 @@ struct InitT { std::tuple t; }; +// V5.2: [5.5.4] `initializer` clause template // struct InitializerT { using InitializerExpr = E; @@ -602,6 +688,7 @@ struct InitializerT { InitializerExpr v; }; +// V5.2: [5.5.10] `in_reduction` clause template // struct InReductionT { using List = ObjectListT; @@ -612,6 +699,7 @@ struct InReductionT { std::tuple t; }; +// V5.2: [5.4.7] `is_device_ptr` clause template // struct IsDevicePtrT { using List = ObjectListT; @@ -619,6 +707,7 @@ struct IsDevicePtrT { List v; }; +// V5.2: [5.4.5] `lastprivate` clause template // struct LastprivateT { using List = ObjectListT; @@ -627,6 +716,7 @@ struct LastprivateT { std::tuple t; }; +// V5.2: [5.4.6] `linear` clause template // struct LinearT { // std::get won't work here due to duplicate types in the tuple. @@ -642,6 +732,7 @@ struct LinearT { t; }; +// V5.2: [5.8.5] `link` clause template // struct LinkT { using List = ObjectListT; @@ -649,6 +740,7 @@ struct LinkT { List v; }; +// V5.2: [5.8.3] `map` clause template // struct MapT { using LocatorList = ObjectListT; @@ -665,16 +757,19 @@ struct MapT { t; }; +// V5.2: [7.5.1] `match` clause template // struct MatchT { using IncompleteTrait = std::true_type; }; +// V5.2: [12.2] `mergeable` clause template // struct MergeableT { using EmptyTrait = std::true_type; }; +// V5.2: [8.5.2] `message` clause template // struct MessageT { using MsgString = E; @@ -682,6 +777,7 @@ struct MessageT { MsgString v; }; +// V5.2: [7.6.2] `nocontext` clause template // struct NocontextT { using DoNotUpdateContext = E; @@ -689,11 +785,13 @@ struct NocontextT { DoNotUpdateContext v; }; +// V5.2: [15.7] `nowait` clause template // struct NogroupT { using EmptyTrait = std::true_type; }; +// V5.2: [10.4.1] `nontemporal` clause template // struct NontemporalT { using List = ObjectListT; @@ -701,26 +799,31 @@ struct NontemporalT { List v; }; +// V5.2: [8.3.1] `assumption` clauses template // struct NoOpenmpT { using EmptyTrait = std::true_type; }; +// V5.2: [8.3.1] `assumption` clauses template // struct NoOpenmpRoutinesT { using EmptyTrait = std::true_type; }; +// V5.2: [8.3.1] `assumption` clauses template // struct NoParallelismT { using EmptyTrait = std::true_type; }; +// V5.2: [7.7.1] `branch` clauses template // struct NotinbranchT { using EmptyTrait = std::true_type; }; +// V5.2: [7.6.1] `novariants` clause template // struct NovariantsT { using DoNotUseVariant = E; @@ -728,11 +831,13 @@ struct NovariantsT { DoNotUseVariant v; }; +// V5.2: [15.6] `nowait` clause template // struct NowaitT { using EmptyTrait = std::true_type; }; +// V5.2: [12.6.2] `num_tasks` clause template // struct NumTasksT { using NumTasks = E; @@ -741,6 +846,7 @@ struct NumTasksT { std::tuple t; }; +// V5.2: [10.2.1] `num_teams` clause template // struct NumTeamsT { using TupleTrait = std::true_type; @@ -749,6 +855,7 @@ struct NumTeamsT { std::tuple t; }; +// V5.2: [10.1.2] `num_threads` clause template // struct NumThreadsT { using Nthreads = E; @@ -772,6 +879,7 @@ struct OmpxDynCgroupMemT { E v; }; +// V5.2: [10.3] `order` clause template // struct OrderT { ENUM(OrderModifier, Reproducible, Unconstrained); @@ -780,6 +888,7 @@ struct OrderT { std::tuple t; }; +// V5.2: [4.4.4] `ordered` clause template // struct OrderedT { using N = E; @@ -787,11 +896,13 @@ struct OrderedT { OPT(N) v; }; +// V5.2: [7.4.2] `otherwise` clause template // struct OtherwiseT { using IncompleteTrait = std::true_type; }; +// V5.2: [9.2.2] `partial` clause template // struct PartialT { using UnrollFactor = E; @@ -799,6 +910,7 @@ struct PartialT { OPT(UnrollFactor) v; }; +// V5.2: [12.4] `priority` clause template // struct PriorityT { using PriorityValue = E; @@ -806,6 +918,7 @@ struct PriorityT { PriorityValue v; }; +// V5.2: [5.4.3] `private` clause template // struct PrivateT { using List = ObjectListT; @@ -813,6 +926,7 @@ struct PrivateT { List v; }; +// V5.2: [10.1.4] `proc_bind` clause template // struct ProcBindT { ENUM(AffinityPolicy, Close, Master, Spread, Primary); @@ -820,11 +934,13 @@ struct ProcBindT { AffinityPolicy v; }; +// V5.2: [15.8.2] Atomic clauses template // struct ReadT { using EmptyTrait = std::true_type; }; +// V5.2: [5.5.8] `reduction` clause template // struct ReductionT { using List = ObjectListT; @@ -836,21 +952,25 @@ struct ReductionT { std::tuple t; }; +// V5.2: [15.8.1] `memory-order` clauses template // struct RelaxedT { using EmptyTrait = std::true_type; }; +// V5.2: [15.8.1] `memory-order` clauses template // struct ReleaseT { using EmptyTrait = std::true_type; }; +// V5.2: [8.2.1] `requirement` clauses template // struct ReverseOffloadT { using EmptyTrait = std::true_type; }; +// V5.2: [10.4.2] `safelen` clause template // struct SafelenT { using Length = E; @@ -858,6 +978,7 @@ struct SafelenT { Length v; }; +// V5.2: [11.5.3] `schedule` clause template // struct ScheduleT { ENUM(Kind, Static, Dynamic, Guided, Auto, Runtime); @@ -868,11 +989,13 @@ struct ScheduleT { std::tuple t; }; +// V5.2: [15.8.1] Memory-order clauses template // struct SeqCstT { using EmptyTrait = std::true_type; }; +// V5.2: [8.5.1] `severity` clause template // struct SeverityT { ENUM(SevLevel, Fatal, Warning); @@ -880,6 +1003,7 @@ struct SeverityT { SevLevel v; }; +// V5.2: [5.4.2] `shared` clause template // struct SharedT { using List = ObjectListT; @@ -887,11 +1011,13 @@ struct SharedT { List v; }; +// V5.2: [15.10.3] `parallelization-level` clauses template // struct SimdT { using EmptyTrait = std::true_type; }; +// V5.2: [10.4.3] `simdlen` clause template // struct SimdlenT { using Length = E; @@ -899,6 +1025,7 @@ struct SimdlenT { Length v; }; +// V5.2: [9.1.1] `sizes` clause template // struct SizesT { using SizeList = ListT; @@ -906,6 +1033,7 @@ struct SizesT { SizeList v; }; +// V5.2: [5.5.9] `task_reduction` clause template // struct TaskReductionT { using List = ObjectListT; @@ -916,6 +1044,7 @@ struct TaskReductionT { std::tuple t; }; +// V5.2: [13.3] `thread_limit` clause template // struct ThreadLimitT { using Threadlim = E; @@ -923,11 +1052,13 @@ struct ThreadLimitT { Threadlim v; }; +// V5.2: [15.10.3] `parallelization-level` clauses template // struct ThreadsT { using EmptyTrait = std::true_type; }; +// V5.2: [5.9.1] `to` clause template // struct ToT { using LocatorList = ObjectListT; @@ -940,16 +1071,19 @@ struct ToT { std::tuple t; }; +// V5.2: [8.2.1] `requirement` clauses template // struct UnifiedAddressT { using EmptyTrait = std::true_type; }; +// V5.2: [8.2.1] `requirement` clauses template // struct UnifiedSharedMemoryT { using EmptyTrait = std::true_type; }; +// V5.2: [5.10] `uniform` clause template // struct UniformT { using ParameterList = ObjectListT; @@ -962,11 +1096,15 @@ struct UnknownT { using EmptyTrait = std::true_type; }; +// V5.2: [12.1] `untied` clause template // struct UntiedT { using EmptyTrait = std::true_type; }; +// Both of the following +// V5.2: [15.8.2] `atomic` clauses +// V5.2: [15.9.3] `update` clause template // struct UpdateT { using TaskDependenceType = tomp::type::TaskDependenceType; @@ -974,6 +1112,7 @@ struct UpdateT { OPT(TaskDependenceType) v; }; +// V5.2: [14.1.3] `use` clause template // struct UseT { using InteropVar = ObjectT; @@ -981,6 +1120,7 @@ struct UseT { InteropVar v; }; +// V5.2: [5.4.10] `use_device_addr` clause template // struct UseDeviceAddrT { using List = ObjectListT; @@ -988,6 +1128,7 @@ struct UseDeviceAddrT { List v; }; +// V5.2: [5.4.8] `use_device_ptr` clause template // struct UseDevicePtrT { using List = ObjectListT; @@ -995,6 +1136,7 @@ struct UseDevicePtrT { List v; }; +// V5.2: [6.8] `uses_allocators` clause template // struct UsesAllocatorsT { using MemSpace = E; @@ -1007,16 +1149,19 @@ struct UsesAllocatorsT { Allocators v; }; +// V5.2: [15.8.3] `extended-atomic` clauses template // struct WeakT { using EmptyTrait = std::true_type; }; +// V5.2: [7.4.1] `when` clause template // struct WhenT { using IncompleteTrait = std::true_type; }; +// V5.2: [15.8.2] Atomic clauses template // struct WriteT { using EmptyTrait = std::true_type; @@ -1120,4 +1265,4 @@ struct ClauseT { #undef OPT #undef ENUM -#endif // FORTRAN_LOWER_OPENMP_CLAUSET_H +#endif // LLVM_FRONTEND_OPENMP_CLAUSET_H -- GitLab From a2982a29fdfcfe2904754815c85f630a4dc6d88c Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Thu, 28 Mar 2024 09:56:14 -0300 Subject: [PATCH 193/541] Revert "[compiler-rt] Allow building builtins.a without a libc (#86737)" This reverts commit 86692258637549ed9f863c3d2ba47b49f61bbc1f. Reverting due to buildbot failures. --- compiler-rt/cmake/config-ix.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 911f48fa1381..46a6fdf8728f 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -235,9 +235,9 @@ set(COMPILER_RT_SUPPORTED_ARCH) # Try to compile a very simple source file to ensure we can target the given # platform. We use the results of these tests to build only the various target # runtime libraries supported by our current compilers cross-compiling -# abilities. Avoids using libc as that may not be available yet. +# abilities. set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) -file(WRITE ${SIMPLE_SOURCE} "int main(void) { return 0; }\n") +file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main(void) { printf(\"hello, world\"); }\n") # Detect whether the current target platform is 32-bit or 64-bit, and setup # the correct commandline flags needed to attempt to target 32-bit and 64-bit. -- GitLab From 96c8e2e88cc68416ddce4a9bf1a9221387b6d4b3 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 28 Mar 2024 12:59:57 +0000 Subject: [PATCH 194/541] [APINotes] For a re-exported module, look for APINotes in the re-exporting module's apinotes file This upstreams https://github.com/apple/llvm-project/pull/8063. If module FooCore is re-exported through module Foo (by using `export_as` in the modulemap), look for attributes of FooCore symbols in Foo.apinotes file. Swift bundles `std.apinotes` file that adds Swift-specific attributes to the C++ stdlib symbols. In recent versions of libc++, module std got split into multiple top-level modules, each of them is re-exported through std. This change allows us to keep using a single modulemap file for all supported C++ stdlibs. rdar://121680760 --- clang/lib/APINotes/APINotesManager.cpp | 5 +++++ clang/test/APINotes/Inputs/Headers/ExportAs.apinotes | 5 +++++ clang/test/APINotes/Inputs/Headers/ExportAs.h | 1 + clang/test/APINotes/Inputs/Headers/ExportAsCore.h | 1 + clang/test/APINotes/Inputs/Headers/module.modulemap | 10 ++++++++++ clang/test/APINotes/export-as.c | 8 ++++++++ 6 files changed, 30 insertions(+) create mode 100644 clang/test/APINotes/Inputs/Headers/ExportAs.apinotes create mode 100644 clang/test/APINotes/Inputs/Headers/ExportAs.h create mode 100644 clang/test/APINotes/Inputs/Headers/ExportAsCore.h create mode 100644 clang/test/APINotes/export-as.c diff --git a/clang/lib/APINotes/APINotesManager.cpp b/clang/lib/APINotes/APINotesManager.cpp index f60f09e2b3c2..789bb97d81de 100644 --- a/clang/lib/APINotes/APINotesManager.cpp +++ b/clang/lib/APINotes/APINotesManager.cpp @@ -221,6 +221,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, ArrayRef SearchPaths) { FileManager &FM = SM.getFileManager(); auto ModuleName = M->getTopLevelModuleName(); + auto ExportedModuleName = M->getTopLevelModule()->ExportAsModule; llvm::SmallVector APINotes; // First, look relative to the module itself. @@ -233,6 +234,10 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, APINotes.push_back(*File); } + // If module FooCore is re-exported through module Foo, try Foo.apinotes. + if (!ExportedModuleName.empty()) + if (auto File = findAPINotesFile(Dir, ExportedModuleName, WantPublic)) + APINotes.push_back(*File); }; if (M->IsFramework) { diff --git a/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes b/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes new file mode 100644 index 000000000000..14c77afd8c30 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes @@ -0,0 +1,5 @@ +Name: ExportAs +Globals: + - Name: globalInt + Availability: none + AvailabilityMsg: "oh no" diff --git a/clang/test/APINotes/Inputs/Headers/ExportAs.h b/clang/test/APINotes/Inputs/Headers/ExportAs.h new file mode 100644 index 000000000000..ff490e096417 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAs.h @@ -0,0 +1 @@ +#include "ExportAsCore.h" diff --git a/clang/test/APINotes/Inputs/Headers/ExportAsCore.h b/clang/test/APINotes/Inputs/Headers/ExportAsCore.h new file mode 100644 index 000000000000..f7674c19935d --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAsCore.h @@ -0,0 +1 @@ +static int globalInt = 123; diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap index 98b4ee3e96cf..99fb1aec8648 100644 --- a/clang/test/APINotes/Inputs/Headers/module.modulemap +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -2,6 +2,16 @@ module ExternCtx { header "ExternCtx.h" } +module ExportAsCore { + header "ExportAsCore.h" + export_as ExportAs +} + +module ExportAs { + header "ExportAs.h" + export * +} + module HeaderLib { header "HeaderLib.h" } diff --git a/clang/test/APINotes/export-as.c b/clang/test/APINotes/export-as.c new file mode 100644 index 000000000000..7a8a652ab755 --- /dev/null +++ b/clang/test/APINotes/export-as.c @@ -0,0 +1,8 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInt -x c | FileCheck %s + +#include "ExportAs.h" + +// CHECK: Dumping globalInt: +// CHECK: VarDecl {{.+}} imported in ExportAsCore globalInt 'int' +// CHECK: UnavailableAttr {{.+}} <> "oh no" -- GitLab From 91856b34e3eddf157ab4c6ea623483b49d149e62 Mon Sep 17 00:00:00 2001 From: "Oleksandr \"Alex\" Zinenko" Date: Thu, 28 Mar 2024 14:00:22 +0100 Subject: [PATCH 195/541] [mlir] move MatchOpInterface under Transform/Interfaces (#86899) This is similar to the TransformOpInterface move. --- mlir/examples/transform/Ch4/include/MyExtension.td | 2 +- .../mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h | 2 +- .../mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td | 2 +- .../SparseTensor/TransformOps/SparseTensorTransformOps.h | 2 +- .../SparseTensor/TransformOps/SparseTensorTransformOps.td | 2 +- .../Dialect/Transform/DebugExtension/DebugExtensionOps.h | 2 +- .../Dialect/Transform/DebugExtension/DebugExtensionOps.td | 2 +- mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt | 4 ---- mlir/include/mlir/Dialect/Transform/IR/TransformOps.h | 2 +- mlir/include/mlir/Dialect/Transform/IR/TransformOps.td | 2 +- .../mlir/Dialect/Transform/Interfaces/CMakeLists.txt | 6 ++++++ .../Dialect/Transform/{IR => Interfaces}/MatchInterfaces.h | 2 +- .../Dialect/Transform/{IR => Interfaces}/MatchInterfaces.td | 0 mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp | 2 +- mlir/lib/Dialect/Transform/IR/CMakeLists.txt | 5 ----- mlir/lib/Dialect/Transform/IR/TransformOps.cpp | 2 +- mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt | 2 ++ .../Transform/{IR => Interfaces}/MatchInterfaces.cpp | 4 ++-- .../lib/Dialect/Transform/TestTransformDialectExtension.h | 2 +- .../lib/Dialect/Transform/TestTransformDialectExtension.td | 2 +- 20 files changed, 24 insertions(+), 25 deletions(-) rename mlir/include/mlir/Dialect/Transform/{IR => Interfaces}/MatchInterfaces.h (99%) rename mlir/include/mlir/Dialect/Transform/{IR => Interfaces}/MatchInterfaces.td (100%) rename mlir/lib/Dialect/Transform/{IR => Interfaces}/MatchInterfaces.cpp (97%) diff --git a/mlir/examples/transform/Ch4/include/MyExtension.td b/mlir/examples/transform/Ch4/include/MyExtension.td index 6c83ff0f46c8..660680334178 100644 --- a/mlir/examples/transform/Ch4/include/MyExtension.td +++ b/mlir/examples/transform/Ch4/include/MyExtension.td @@ -14,7 +14,7 @@ #ifndef MY_EXTENSION #define MY_EXTENSION -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h index d6bbcf88b79f..fdebcb031b11 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h @@ -10,8 +10,8 @@ #define MLIR_DIALECT_LINALG_TRANSFORMOPS_LINALGMATCHOPS_H #include "mlir/Dialect/Linalg/IR/Linalg.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" namespace mlir { namespace transform { diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td index dfeb8ae5d5dd..cdc29d053e5a 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td @@ -10,7 +10,7 @@ #define LINALG_MATCH_OPS include "mlir/Dialect/Linalg/TransformOps/LinalgTransformEnums.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" diff --git a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h index 54a9e2aec805..8c3124909052 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h +++ b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h @@ -9,9 +9,9 @@ #ifndef MLIR_DIALECT_SPARSETENSOR_TRANSFORMOPS_SPARSETENSORTRANSFORMOPS_H #define MLIR_DIALECT_SPARSETENSOR_TRANSFORMOPS_SPARSETENSORTRANSFORMOPS_H -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" #include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/RegionKindInterface.h" diff --git a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td index 9f0436e701b8..e340228795cd 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td +++ b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td @@ -11,7 +11,7 @@ #ifndef SPARSETENSOR_TRANSFORM_OPS #define SPARSETENSOR_TRANSFORM_OPS -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" diff --git a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h index 05abe5adbe80..ea541c9515b8 100644 --- a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h +++ b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h @@ -10,8 +10,8 @@ #define MLIR_DIALECT_TRANSFORM_DEBUGEXTENSION_DEBUGEXTENSIONOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" #include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" diff --git a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td index dc9b7c4229ac..0275f241fda3 100644 --- a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td +++ b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td @@ -16,7 +16,7 @@ include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" diff --git a/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt index e90d04a20244..df5af7ae710d 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt @@ -24,7 +24,3 @@ add_dependencies(mlir-headers MLIRTransformDialectEnumIncGen) add_mlir_dialect(TransformOps transform) add_mlir_doc(TransformOps TransformOps Dialects/ -gen-op-doc -dialect=transform) -add_mlir_interface(MatchInterfaces) -add_dependencies(MLIRMatchInterfacesIncGen MLIRTransformInterfacesIncGen) -add_mlir_doc(MatchInterfaces MatchOpInterfaces Dialects/ -gen-op-interface-docs) - diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h index 6c10fcf75804..88185a07966d 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h @@ -10,10 +10,10 @@ #define MLIR_DIALECT_TRANSFORM_IR_TRANSFORMOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" #include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td index 9caa7632c177..bf1a8016cd9d 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td @@ -18,7 +18,7 @@ include "mlir/Interfaces/FunctionInterfaces.td" include "mlir/IR/OpAsmInterface.td" include "mlir/IR/RegionKindInterface.td" include "mlir/IR/SymbolInterfaces.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" diff --git a/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt b/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt index b3396b67b4f7..14ce5b82b811 100644 --- a/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt @@ -9,3 +9,9 @@ mlir_tablegen(TransformTypeInterfaces.cpp.inc -gen-type-interface-defs) add_public_tablegen_target(MLIRTransformDialectTypeInterfacesIncGen) add_dependencies(mlir-headers MLIRTransformDialectTypeInterfacesIncGen) add_mlir_doc(TransformInterfaces TransformTypeInterfaces Dialects/ -gen-type-interface-docs) + +add_mlir_interface(MatchInterfaces) +add_dependencies(MLIRMatchInterfacesIncGen MLIRTransformInterfacesIncGen) +add_dependencies(mlir-headers MLIRMatchInterfacesIncGen) +add_mlir_doc(MatchInterfaces MatchOpInterfaces Dialects/ -gen-op-interface-docs) + diff --git a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h b/mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.h similarity index 99% rename from mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h rename to mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.h index 13a52b54201e..ad3e375c326f 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.h @@ -218,6 +218,6 @@ expandTargetSpecification(Location loc, bool isAll, bool isInverted, } // namespace transform } // namespace mlir -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h.inc" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h.inc" #endif // MLIR_DIALECT_TRANSFORM_IR_MATCHINTERFACES_H diff --git a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td b/mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.td similarity index 100% rename from mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td rename to mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.td diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp index ae2a34bcf3e5..3e85559e1ec0 100644 --- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp +++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp @@ -12,8 +12,8 @@ #include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h" #include "mlir/Dialect/Linalg/TransformOps/Syntax.h" #include "mlir/Dialect/Linalg/Utils/Utils.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/Interfaces/FunctionImplementation.h" #include "llvm/Support/Debug.h" diff --git a/mlir/lib/Dialect/Transform/IR/CMakeLists.txt b/mlir/lib/Dialect/Transform/IR/CMakeLists.txt index f90ac089adaa..5b4989f328e6 100644 --- a/mlir/lib/Dialect/Transform/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/Transform/IR/CMakeLists.txt @@ -1,15 +1,10 @@ add_mlir_dialect_library(MLIRTransformDialect - MatchInterfaces.cpp TransformAttrs.cpp TransformDialect.cpp TransformOps.cpp TransformTypes.cpp Utils.cpp - DEPENDS - MLIRMatchInterfacesIncGen - MLIRTransformDialectIncGen - LINK_LIBS PUBLIC MLIRCastInterfaces MLIRFunctionInterfaces diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp index abd557a508a1..942341093817 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp @@ -11,10 +11,10 @@ #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h" #include "mlir/Conversion/LLVMCommon/ConversionTarget.h" #include "mlir/Conversion/LLVMCommon/TypeConverter.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" #include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Diagnostics.h" diff --git a/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt b/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt index 7b837bde0625..fc9cbfdc9a5b 100644 --- a/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt +++ b/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt @@ -1,7 +1,9 @@ add_mlir_library(MLIRTransformDialectInterfaces + MatchInterfaces.cpp TransformInterfaces.cpp DEPENDS + MLIRMatchInterfacesIncGen MLIRTransformInterfacesIncGen LINK_LIBS PUBLIC diff --git a/mlir/lib/Dialect/Transform/IR/MatchInterfaces.cpp b/mlir/lib/Dialect/Transform/Interfaces/MatchInterfaces.cpp similarity index 97% rename from mlir/lib/Dialect/Transform/IR/MatchInterfaces.cpp rename to mlir/lib/Dialect/Transform/Interfaces/MatchInterfaces.cpp index b9b6dabc2621..4151d0ea5bee 100644 --- a/mlir/lib/Dialect/Transform/IR/MatchInterfaces.cpp +++ b/mlir/lib/Dialect/Transform/Interfaces/MatchInterfaces.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" using namespace mlir; @@ -149,4 +149,4 @@ DiagnosedSilenceableFailure transform::expandTargetSpecification( // Generated interface implementation. //===----------------------------------------------------------------------===// -#include "mlir/Dialect/Transform/IR/MatchInterfaces.cpp.inc" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.cpp.inc" diff --git a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h index ddc38b993564..60dc959b0050 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h @@ -16,8 +16,8 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/PDL/IR/PDLTypes.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" #include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" diff --git a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td index 75134b25882f..4f2cf34f7d33 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td @@ -17,7 +17,7 @@ include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/AttrTypeBase.td" include "mlir/IR/OpBase.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/PDL/IR/PDLTypes.td" -- GitLab From eacda36c7dd842cb15c0c954eda74b67d0c73814 Mon Sep 17 00:00:00 2001 From: Rolf Morel Date: Thu, 28 Mar 2024 13:13:08 +0000 Subject: [PATCH 196/541] [SCF][Transform] Add support for scf.for in LoopFuseSibling op (#81495) Adds support for fusing two scf.for loops occurring in the same block. Uses the rudimentary checks already in place for scf.forall (like the target loop's operands being dominated by the source loop). - Fixes a bug in the dominance check whereby it was checked that values in the target loop themselves dominated the source loop rather than the ops that define these operands. - Renames the LoopFuseSibling op to LoopFuseSiblingOp. - Updates LoopFuseSiblingOp's description. - Adds tests for using LoopFuseSiblingOp on scf.for loops, including one which fails without the fix for the dominance check. - Adds tests checking the different failure modes of the dominance checker. - Adds test for case whereby scf.yield is automatically generated when there are no loop-carried variables. --- .../SCF/TransformOps/SCFTransformOps.td | 23 +- mlir/include/mlir/Dialect/SCF/Utils/Utils.h | 10 + .../SCF/TransformOps/SCFTransformOps.cpp | 66 +++-- mlir/lib/Dialect/SCF/Utils/Utils.cpp | 99 ++++--- .../SCF/transform-loop-fuse-sibling.mlir | 251 ++++++++++++++++-- 5 files changed, 357 insertions(+), 92 deletions(-) diff --git a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td index 6f94cee5b019..5eefe2664d0a 100644 --- a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td +++ b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td @@ -333,23 +333,24 @@ def TakeAssumedBranchOp : Op]> { let summary = "Fuse a loop into another loop, assuming the fusion is legal."; let description = [{ Fuses the `target` loop into the `source` loop assuming they are - independent of each other. It is the responsibility of the user to ensure - that the given two loops are independent of each other, this operation will - not performa any legality checks and will simply fuse the two given loops. + independent of each other. In the fused loop, the arguments, body and + results of `target` are placed _before_ those of `source`. - Currently, the only fusion supported is when both `target` and `source` - are `scf.forall` operations. For `scf.forall` fusion, the bounds and the - mapping must match, otherwise a silencable failure is produced. + For fusion of two `scf.for` loops, the bounds and step size must match. For + fusion of two `scf.forall` loops, the bounds and the mapping must match. + Otherwise a silencable failure is produced. - The input handles `target` and `source` must map to exactly one operation, - a definite failure is produced otherwise. + The `target` and `source` handles must refer to exactly one operation, + otherwise a definite failure is produced. It is the responsibility of the + user to ensure that the `target` and `source` loops are independent of each + other -- this op will only perform rudimentary legality checks. #### Return modes @@ -362,10 +363,6 @@ def LoopFuseSibling : Op - ]; } #endif // SCF_TRANSFORM_OPS diff --git a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h index 9bdd6eb83387..883d11bcc4df 100644 --- a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h +++ b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h @@ -162,6 +162,16 @@ scf::ForallOp fuseIndependentSiblingForallLoops(scf::ForallOp target, scf::ForallOp source, RewriterBase &rewriter); +/// Given two scf.for loops, `target` and `source`, fuses `target` into +/// `source`. Assumes that the given loops are siblings and are independent of +/// each other. +/// +/// This function does not perform any legality checks and simply fuses the +/// loops. The caller is responsible for ensuring that the loops are legal to +/// fuse. +scf::ForOp fuseIndependentSiblingForLoops(scf::ForOp target, scf::ForOp source, + RewriterBase &rewriter); + } // namespace mlir #endif // MLIR_DIALECT_SCF_UTILS_UTILS_H_ diff --git a/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp b/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp index 4d8d93f7aac7..c09184148208 100644 --- a/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp +++ b/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp @@ -384,7 +384,7 @@ void transform::TakeAssumedBranchOp::getEffects( } //===----------------------------------------------------------------------===// -// LoopFuseSibling +// LoopFuseSiblingOp //===----------------------------------------------------------------------===// /// Check if `target` and `source` are siblings, in the context that `target` @@ -408,7 +408,7 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, // Check if fusion will violate dominance. DominanceInfo domInfo(source); if (target->isBeforeInBlock(source)) { - // Since, `target` is before `source`, all users of results of `target` + // Since `target` is before `source`, all users of results of `target` // need to be dominated by `source`. for (Operation *user : target->getUsers()) { if (!domInfo.properlyDominates(source, user, /*enclosingOpOk=*/false)) { @@ -424,9 +424,8 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, // Check if operands of `target` are dominated by `source`. for (Value operand : target->getOperands()) { Operation *operandOp = operand.getDefiningOp(); - // If operand does not have a defining operation, it is a block arguement, - // which will always dominate `source`, since `target` and `source` are in - // the same block and the operand dominated `source` before. + // Operands without defining operations are block arguments. When `target` + // and `source` occur in the same block, these operands dominate `source`. if (!operandOp) continue; @@ -441,8 +440,11 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, bool failed = false; OpOperand *failedValue = nullptr; visitUsedValuesDefinedAbove(target->getRegions(), [&](OpOperand *operand) { - if (!domInfo.properlyDominates(operand->getOwner(), source, - /*enclosingOpOk=*/false)) { + Operation *operandOp = operand->get().getDefiningOp(); + if (operandOp && !domInfo.properlyDominates(operandOp, source, + /*enclosingOpOk=*/false)) { + // `operand` is not an argument of an enclosing block and the defining + // op of `operand` is outside `target` but does not dominate `source`. failed = true; failedValue = operand; } @@ -457,12 +459,11 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, return DiagnosedSilenceableFailure::success(); } -/// Check if `target` can be fused into `source`. +/// Check if `target` scf.forall can be fused into `source` scf.forall. /// -/// This is a simple check that just checks if both loops have same -/// bounds, steps and mapping. This check does not ensure that the side effects -/// of `target` are independent of `source` or vice-versa. It is the -/// responsibility of the caller to ensure that. +/// This simply checks if both loops have the same bounds, steps and mapping. +/// No attempt is made at checking that the side effects of `target` and +/// `source` are independent of each other. static bool isForallWithIdenticalConfiguration(Operation *target, Operation *source) { auto targetOp = dyn_cast(target); @@ -476,21 +477,27 @@ static bool isForallWithIdenticalConfiguration(Operation *target, targetOp.getMapping() == sourceOp.getMapping(); } -/// Fuse `target` into `source` assuming they are siblings and indepndent. -/// TODO: Add fusion for more operations. Currently, we handle only scf.forall. -static Operation *fuseSiblings(Operation *target, Operation *source, - RewriterBase &rewriter) { - auto targetOp = dyn_cast(target); - auto sourceOp = dyn_cast(source); +/// Check if `target` scf.for can be fused into `source` scf.for. +/// +/// This simply checks if both loops have the same bounds and steps. No attempt +/// is made at checking that the side effects of `target` and `source` are +/// independent of each other. +static bool isForWithIdenticalConfiguration(Operation *target, + Operation *source) { + auto targetOp = dyn_cast(target); + auto sourceOp = dyn_cast(source); if (!targetOp || !sourceOp) - return nullptr; - return fuseIndependentSiblingForallLoops(targetOp, sourceOp, rewriter); + return false; + + return targetOp.getLowerBound() == sourceOp.getLowerBound() && + targetOp.getUpperBound() == sourceOp.getUpperBound() && + targetOp.getStep() == sourceOp.getStep(); } DiagnosedSilenceableFailure -transform::LoopFuseSibling::apply(transform::TransformRewriter &rewriter, - transform::TransformResults &results, - transform::TransformState &state) { +transform::LoopFuseSiblingOp::apply(transform::TransformRewriter &rewriter, + transform::TransformResults &results, + transform::TransformState &state) { auto targetOps = state.getPayloadOps(getTarget()); auto sourceOps = state.getPayloadOps(getSource()); @@ -510,13 +517,18 @@ transform::LoopFuseSibling::apply(transform::TransformRewriter &rewriter, if (!diag.succeeded()) return diag; - // Check if the target can be fused into source. - if (!isForallWithIdenticalConfiguration(target, source)) { + Operation *fusedLoop; + /// TODO: Support fusion for loop-like ops besides scf.for and scf.forall. + if (isForWithIdenticalConfiguration(target, source)) { + fusedLoop = fuseIndependentSiblingForLoops( + cast(target), cast(source), rewriter); + } else if (isForallWithIdenticalConfiguration(target, source)) { + fusedLoop = fuseIndependentSiblingForallLoops( + cast(target), cast(source), rewriter); + } else return emitSilenceableFailure(target->getLoc()) << "operations cannot be fused"; - } - Operation *fusedLoop = fuseSiblings(target, source, rewriter); assert(fusedLoop && "failed to fuse operations"); results.set(cast(getFusedLoop()), {fusedLoop}); diff --git a/mlir/lib/Dialect/SCF/Utils/Utils.cpp b/mlir/lib/Dialect/SCF/Utils/Utils.cpp index 502d7e197a6f..914aeb4fa79f 100644 --- a/mlir/lib/Dialect/SCF/Utils/Utils.cpp +++ b/mlir/lib/Dialect/SCF/Utils/Utils.cpp @@ -910,61 +910,98 @@ scf::ForallOp mlir::fuseIndependentSiblingForallLoops(scf::ForallOp target, unsigned numTargetOuts = target.getNumResults(); unsigned numSourceOuts = source.getNumResults(); - OperandRange targetOuts = target.getOutputs(); - OperandRange sourceOuts = source.getOutputs(); - // Create fused shared_outs. SmallVector fusedOuts; - fusedOuts.reserve(numTargetOuts + numSourceOuts); - fusedOuts.append(targetOuts.begin(), targetOuts.end()); - fusedOuts.append(sourceOuts.begin(), sourceOuts.end()); + llvm::append_range(fusedOuts, target.getOutputs()); + llvm::append_range(fusedOuts, source.getOutputs()); - // Create a new scf::forall op after the source loop. + // Create a new scf.forall op after the source loop. rewriter.setInsertionPointAfter(source); scf::ForallOp fusedLoop = rewriter.create( source.getLoc(), source.getMixedLowerBound(), source.getMixedUpperBound(), source.getMixedStep(), fusedOuts, source.getMapping()); // Map control operands. - IRMapping fusedMapping; - fusedMapping.map(target.getInductionVars(), fusedLoop.getInductionVars()); - fusedMapping.map(source.getInductionVars(), fusedLoop.getInductionVars()); + IRMapping mapping; + mapping.map(target.getInductionVars(), fusedLoop.getInductionVars()); + mapping.map(source.getInductionVars(), fusedLoop.getInductionVars()); // Map shared outs. - fusedMapping.map(target.getRegionIterArgs(), - fusedLoop.getRegionIterArgs().slice(0, numTargetOuts)); - fusedMapping.map( - source.getRegionIterArgs(), - fusedLoop.getRegionIterArgs().slice(numTargetOuts, numSourceOuts)); + mapping.map(target.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_front(numTargetOuts)); + mapping.map(source.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_back(numSourceOuts)); // Append everything except the terminator into the fused operation. rewriter.setInsertionPointToStart(fusedLoop.getBody()); for (Operation &op : target.getBody()->without_terminator()) - rewriter.clone(op, fusedMapping); + rewriter.clone(op, mapping); for (Operation &op : source.getBody()->without_terminator()) - rewriter.clone(op, fusedMapping); + rewriter.clone(op, mapping); // Fuse the old terminator in_parallel ops into the new one. scf::InParallelOp targetTerm = target.getTerminator(); scf::InParallelOp sourceTerm = source.getTerminator(); scf::InParallelOp fusedTerm = fusedLoop.getTerminator(); - rewriter.setInsertionPointToStart(fusedTerm.getBody()); for (Operation &op : targetTerm.getYieldingOps()) - rewriter.clone(op, fusedMapping); + rewriter.clone(op, mapping); for (Operation &op : sourceTerm.getYieldingOps()) - rewriter.clone(op, fusedMapping); - - // Replace all uses of the old loops with the fused loop. - rewriter.replaceAllUsesWith(target.getResults(), - fusedLoop.getResults().slice(0, numTargetOuts)); - rewriter.replaceAllUsesWith( - source.getResults(), - fusedLoop.getResults().slice(numTargetOuts, numSourceOuts)); - - // Erase the old loops. - rewriter.eraseOp(target); - rewriter.eraseOp(source); + rewriter.clone(op, mapping); + + // Replace old loops by substituting their uses by results of the fused loop. + rewriter.replaceOp(target, fusedLoop.getResults().take_front(numTargetOuts)); + rewriter.replaceOp(source, fusedLoop.getResults().take_back(numSourceOuts)); + + return fusedLoop; +} + +scf::ForOp mlir::fuseIndependentSiblingForLoops(scf::ForOp target, + scf::ForOp source, + RewriterBase &rewriter) { + unsigned numTargetOuts = target.getNumResults(); + unsigned numSourceOuts = source.getNumResults(); + + // Create fused init_args, with target's init_args before source's init_args. + SmallVector fusedInitArgs; + llvm::append_range(fusedInitArgs, target.getInitArgs()); + llvm::append_range(fusedInitArgs, source.getInitArgs()); + + // Create a new scf.for op after the source loop (with scf.yield terminator + // (without arguments) only in case its init_args is empty). + rewriter.setInsertionPointAfter(source); + scf::ForOp fusedLoop = rewriter.create( + source.getLoc(), source.getLowerBound(), source.getUpperBound(), + source.getStep(), fusedInitArgs); + + // Map original induction variables and operands to those of the fused loop. + IRMapping mapping; + mapping.map(target.getInductionVar(), fusedLoop.getInductionVar()); + mapping.map(target.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_front(numTargetOuts)); + mapping.map(source.getInductionVar(), fusedLoop.getInductionVar()); + mapping.map(source.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_back(numSourceOuts)); + + // Merge target's body into the new (fused) for loop and then source's body. + rewriter.setInsertionPointToStart(fusedLoop.getBody()); + for (Operation &op : target.getBody()->without_terminator()) + rewriter.clone(op, mapping); + for (Operation &op : source.getBody()->without_terminator()) + rewriter.clone(op, mapping); + + // Build fused yield results by appropriately mapping original yield operands. + SmallVector yieldResults; + for (Value operand : target.getBody()->getTerminator()->getOperands()) + yieldResults.push_back(mapping.lookupOrDefault(operand)); + for (Value operand : source.getBody()->getTerminator()->getOperands()) + yieldResults.push_back(mapping.lookupOrDefault(operand)); + if (!yieldResults.empty()) + rewriter.create(source.getLoc(), yieldResults); + + // Replace old loops by substituting their uses by results of the fused loop. + rewriter.replaceOp(target, fusedLoop.getResults().take_front(numTargetOuts)); + rewriter.replaceOp(source, fusedLoop.getResults().take_back(numSourceOuts)); return fusedLoop; } diff --git a/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir b/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir index faaa2db3aa57..0f51b1cdbe0c 100644 --- a/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir +++ b/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir @@ -1,14 +1,113 @@ // RUN: mlir-opt %s -transform-interpreter --cse --canonicalize -split-input-file -verify-diagnostics | FileCheck %s +// RUN: mlir-opt %s -transform-interpreter -split-input-file -verify-diagnostics | FileCheck %s --check-prefix CHECK-NOCLEANUP -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { +// CHECK: func.func @fuse_1st_for_into_2nd([[A:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @fuse_1st_for_into_2nd(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + // CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index + // CHECK-DAG: [[C16:%.*]] = arith.constant 16 : index + // CHECK-DAG: [[C128:%.*]] = arith.constant 128 : index + // CHECK-DAG: [[ZERO:%.*]] = arith.constant 0.000000e+00 : f32 + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // CHECK: [[R0:%.*]]:2 = scf.for [[IV:%.*]] = [[C0]] to [[C128]] step [[C16]] iter_args([[IA:%.*]] = [[A]], [[IB:%.*]] = [[B]]) {{.*}} + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + // CHECK-DAG: [[ASLICE:%.*]] = vector.transfer_read [[A]][[[IV]]], [[ZERO]] + // CHECK-DAG: [[SLICE0:%.*]] = vector.transfer_read [[IA]][[[IV]]], [[ZERO]] + // CHECK: [[OUT1:%.*]] = arith.addf [[SLICE0]], [[ASLICE]] + // CHECK-NEXT: [[WRT0:%.*]] = vector.transfer_write [[OUT1]], [[IA]][[[IV]]] + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %B) -> (tensor<128xf32>) { + // CHECK-DAG: [[SLICE1:%.*]] = vector.transfer_read [[IB]][[[IV]]], [[ZERO]] + // CHECK: [[OUT2:%.*]] = arith.addf [[SLICE1]], [[ASLICE]] + // CHECK-NEXT: [[WRT1:%.*]] = vector.transfer_write [[OUT2]], [[IB]][[[IV]]] + %dup2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + // CHECK: scf.yield [[WRT0]], [[WRT1]] : {{.*}} + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#0 into %for#1 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +// CHECK: func.func @fuse_2nd_for_into_1st([[A:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @fuse_2nd_for_into_1st(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + // CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index + // CHECK-DAG: [[C16:%.*]] = arith.constant 16 : index + // CHECK-DAG: [[C128:%.*]] = arith.constant 128 : index + // CHECK-DAG: [[ZERO:%.*]] = arith.constant 0.000000e+00 : f32 + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // CHECK: [[R0:%.*]]:2 = scf.for [[IV:%.*]] = [[C0]] to [[C128]] step [[C16]] iter_args([[IB:%.*]] = [[B]], [[IA:%.*]] = [[A]]) {{.*}} + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + // CHECK-DAG: [[ASLICE:%.*]] = vector.transfer_read [[A]][[[IV]]], [[ZERO]] + // CHECK-DAG: [[SLICE0:%.*]] = vector.transfer_read [[IB]][[[IV]]], [[ZERO]] + // CHECK: [[OUT1:%.*]] = arith.addf [[SLICE0]], [[ASLICE]] + // CHECK-NEXT: [[WRT0:%.*]] = vector.transfer_write [[OUT1]], [[IB]][[[IV]]] + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %B) -> (tensor<128xf32>) { + // CHECK-DAG: [[SLICE1:%.*]] = vector.transfer_read [[IA]][[[IV]]], [[ZERO]] + // CHECK: [[OUT2:%.*]] = arith.addf [[SLICE1]], [[ASLICE]] + // CHECK-NEXT: [[WRT1:%.*]] = vector.transfer_write [[OUT2]], [[IA]][[[IV]]] + %dup2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + // NB: the dominance check used to fail on the following line, + // however the defining op for the value of %arg3 occurs above the source loop and hence is safe + // and %arg4 is a block argument of the scope of the loops and hence is safe + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + // CHECK: scf.yield [[WRT0]], [[WRT1]] : {{.*}} + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#1 into %for#0 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +// CHECK: func.func @matmul_fuse_1st_forall_into_2nd([[A1:%.*]]: {{.*}}, [[A2:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @matmul_fuse_1st_forall_into_2nd(%A1 : tensor<128x128xf32>, %A2 : tensor<128x128xf32>, %B : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { %zero = arith.constant 0.0 : f32 %out_alloc = tensor.empty() : tensor<128x128xf32> %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> // CHECK: scf.forall ([[I:%.*]]) in (4) shared_outs([[S1:%.*]] = [[IN1:%.*]], [[S2:%.*]] = [[IN2:%.*]]) -> (tensor<128x128xf32>, tensor<128x128xf32>) { // CHECK: [[T:%.*]] = affine.apply + // CHECK: tensor.extract_slice [[A2]][[[T]], 0] [32, 128] [1, 1] // CHECK: tensor.extract_slice [[S1]][[[T]], 0] [32, 128] [1, 1] // CHECK: [[OUT1:%.*]] = linalg.matmul + // CHECK: tensor.extract_slice [[A1]][[[T]], 0] [32, 128] [1, 1] // CHECK: tensor.extract_slice [[S2]][[[T]], 0] [32, 128] [1, 1] // CHECK: [[OUT2:%.*]] = linalg.matmul // CHECK: scf.forall.in_parallel { @@ -16,12 +115,11 @@ func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tenso // CHECK: tensor.parallel_insert_slice [[OUT2]] into [[S2]][[[T]], 0] [32, 128] [1, 1] // CHECK: } // CHECK: } - %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> - %out2 = linalg.matmul ins(%A, %B2 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + %out1 = linalg.matmul ins(%A1, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + %out2 = linalg.matmul ins(%A2, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) @@ -31,25 +129,37 @@ module attributes {transform.with_named_sequence} { %tiled_mm1, %loop1 = transform.structured.tile_using_forall %mm1 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) %tiled_mm2, %loop2 = transform.structured.tile_using_forall %mm2 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) - %fused_loop = transform.loop.fuse_sibling %loop1 into %loop2 : (!transform.any_op, !transform.any_op) -> !transform.any_op + %fused_loop = transform.loop.fuse_sibling %loop2 into %loop1 : (!transform.any_op, !transform.any_op) -> !transform.any_op transform.yield } } // ----- -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { +// CHECK: func.func @matmul_fuse_2nd_forall_into_1st([[A1:%.*]]: {{.*}}, [[A2:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @matmul_fuse_2nd_forall_into_1st(%A1 : tensor<128x128xf32>, %A2 : tensor<128x128xf32>, %B : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { %zero = arith.constant 0.0 : f32 %out_alloc = tensor.empty() : tensor<128x128xf32> %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> - // expected-error @below {{user of results of target should be properly dominated by source}} - %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> - %out2 = linalg.matmul ins(%A, %out1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + // CHECK: scf.forall ([[I:%.*]]) in (4) shared_outs([[S1:%.*]] = [[IN1:%.*]], [[S2:%.*]] = [[IN2:%.*]]) -> (tensor<128x128xf32>, tensor<128x128xf32>) { + // CHECK: [[T:%.*]] = affine.apply + // CHECK: tensor.extract_slice [[A1]][[[T]], 0] [32, 128] [1, 1] + // CHECK: tensor.extract_slice [[S1]][[[T]], 0] [32, 128] [1, 1] + // CHECK: [[OUT1:%.*]] = linalg.matmul + // CHECK: tensor.extract_slice [[A2]][[[T]], 0] [32, 128] [1, 1] + // CHECK: tensor.extract_slice [[S2]][[[T]], 0] [32, 128] [1, 1] + // CHECK: [[OUT2:%.*]] = linalg.matmul + // CHECK: scf.forall.in_parallel { + // CHECK: tensor.parallel_insert_slice [[OUT1]] into [[S1]][[[T]], 0] [32, 128] [1, 1] + // CHECK: tensor.parallel_insert_slice [[OUT2]] into [[S2]][[[T]], 0] [32, 128] [1, 1] + // CHECK: } + // CHECK: } + %out1 = linalg.matmul ins(%A1, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + %out2 = linalg.matmul ins(%A2, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) @@ -66,18 +176,84 @@ module attributes {transform.with_named_sequence} { // ----- -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { +// CHECK-NOCLEANUP: func.func @fuse_no_iter_args([[A:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @fuse_no_iter_args(%A: tensor<128xf32>, %B: tensor<128xf32>) { + // CHECK-NOCLEANUP: [[C0:%.*]] = arith.constant 0 : index + // CHECK-NOCLEANUP: [[C16:%.*]] = arith.constant 16 : index + // CHECK-NOCLEANUP: [[C128:%.*]] = arith.constant 128 : index + // CHECK-NOCLEANUP: [[ZERO:%.*]] = arith.constant 0.000000e+00 : f32 + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // CHECK-NOCLEANUP: scf.for [[IV:%.*]] = [[C0]] to [[C128]] step [[C16]] {{.*}} + scf.for %arg0 = %c0 to %c128 step %c16 { + // CHECK-NOCLEANUP: [[ASLICE:%.*]] = vector.transfer_read [[A]][[[IV]]], [[ZERO]] + %2 = vector.transfer_read %A[%arg0], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + scf.yield + } + scf.for %arg0 = %c0 to %c128 step %c16 { + // CHECK-NOCLEANUP: [[BSLICE:%.*]] = vector.transfer_read [[B]][[[IV]]], [[ZERO]] + %dup2 = vector.transfer_read %B[%arg0], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + scf.yield + } + return +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#0 into %for#1 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +func.func @source_for_uses_result_of_target_for_err(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // expected-error @below {{user of results of target should be properly dominated by source}} + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %1) -> (tensor<128xf32>) { + %dup2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#0 into %for#1 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +func.func @source_forall_uses_result_of_target_forall_err(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { %zero = arith.constant 0.0 : f32 %out_alloc = tensor.empty() : tensor<128x128xf32> %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> + // expected-error @below {{user of results of target should be properly dominated by source}} %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> - // expected-error @below {{values used inside regions of target should be properly dominated by source}} %out2 = linalg.matmul ins(%A, %out1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) @@ -87,25 +263,58 @@ module attributes {transform.with_named_sequence} { %tiled_mm1, %loop1 = transform.structured.tile_using_forall %mm1 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) %tiled_mm2, %loop2 = transform.structured.tile_using_forall %mm2 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) - %fused_loop = transform.loop.fuse_sibling %loop2 into %loop1 : (!transform.any_op, !transform.any_op) -> !transform.any_op + %fused_loop = transform.loop.fuse_sibling %loop1 into %loop2 : (!transform.any_op, !transform.any_op) -> !transform.any_op transform.yield } } // ----- -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { - %zero = arith.constant 0.0 : f32 - %out_alloc = tensor.empty() : tensor<128x128xf32> - %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> +func.func @target_for_region_uses_result_of_source_for_err(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %B) -> (tensor<128xf32>) { + // expected-error @below {{values used inside regions of target should be properly dominated by source}} + %dup2 = vector.transfer_read %1[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#1 into %for#0 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} - %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> +// ----- + +func.func @target_forall_depends_on_value_not_dominated_by_source_forall_err(%A1 : tensor<128x128xf32>, %A2 : tensor<128x128xf32>, %B : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { + %zero = arith.constant 0.0 : f32 + %buf1_alloc = tensor.empty() : tensor<128x128xf32> + %buf1 = linalg.fill ins(%zero : f32) outs(%buf1_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> + %out1 = linalg.matmul ins(%A1, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%buf1 : tensor<128x128xf32>) -> tensor<128x128xf32> + %out_alloc2 = tensor.empty() : tensor<128x128xf32> + %buf2 = linalg.fill ins(%zero : f32) outs(%buf1_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> // expected-error @below {{operands of target should be properly dominated by source}} - %out2 = linalg.matmul ins(%A, %B2 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out1 : tensor<128x128xf32>) -> tensor<128x128xf32> + %out2 = linalg.matmul ins(%A2, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%buf2 : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) -- GitLab From a3efc53f168b1451803a40075201c3490d6e3928 Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Thu, 28 Mar 2024 09:18:45 -0400 Subject: [PATCH 197/541] [AIX][TLS] Produce a faster local-exec access sequence for the "aix-small-tls" global variable attribute (#83053) Similar to 3f46e5453d9310b15d974e876f6132e3cf50c4b1, this patch allows the backend to produce a faster access sequence for the local-exec TLS model, where loading from the TOC can be avoided, for local-exec TLS variables that are annotated with the "aix-small-tls" attribute. The expectation is for local-exec TLS variables to be set with this attribute through PGO. Furthermore, the optimized access sequence is only generated for local-exec TLS variables annotated with "aix-small-tls", only if they are less than ~32KB in size. --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 28 ++- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 23 +- .../aix-small-tls-globalvarattr-funcattr.ll | 105 +++++++++ .../aix-small-tls-globalvarattr-loadaddr.ll | 222 ++++++++++++++++++ .../aix-small-tls-globalvarattr-targetattr.ll | 53 +++++ 5 files changed, 416 insertions(+), 15 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll create mode 100644 llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-loadaddr.ll create mode 100644 llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-targetattr.ll diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index dfea9e770924..af82b6cdb180 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -7558,6 +7558,16 @@ static void reduceVSXSwap(SDNode *N, SelectionDAG *DAG) { DAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), N->getOperand(0)); } +// Check if an SDValue has the 'aix-small-tls' global variable attribute. +static bool hasAIXSmallTLSAttr(SDValue Val) { + if (GlobalAddressSDNode *GA = dyn_cast(Val)) + if (const GlobalVariable *GV = dyn_cast(GA->getGlobal())) + if (GV->hasAttribute("aix-small-tls")) + return true; + + return false; +} + // Is an ADDI eligible for folding for non-TOC-based local-exec accesses? static bool isEligibleToFoldADDIForLocalExecAccesses(SelectionDAG *DAG, SDValue ADDIToFold) { @@ -7567,20 +7577,25 @@ static bool isEligibleToFoldADDIForLocalExecAccesses(SelectionDAG *DAG, (ADDIToFold.getMachineOpcode() != PPC::ADDI8)) return false; + // Folding is only allowed for the AIX small-local-exec TLS target attribute + // or when the 'aix-small-tls' global variable attribute is present. + const PPCSubtarget &Subtarget = + DAG->getMachineFunction().getSubtarget(); + SDValue TLSVarNode = ADDIToFold.getOperand(1); + if (!(Subtarget.hasAIXSmallLocalExecTLS() || hasAIXSmallTLSAttr(TLSVarNode))) + return false; + // The first operand of the ADDIToFold should be the thread pointer. // This transformation is only performed if the first operand of the // addi is the thread pointer. SDValue TPRegNode = ADDIToFold.getOperand(0); RegisterSDNode *TPReg = dyn_cast(TPRegNode.getNode()); - const PPCSubtarget &Subtarget = - DAG->getMachineFunction().getSubtarget(); if (!TPReg || (TPReg->getReg() != Subtarget.getThreadPointerRegister())) return false; // The second operand of the ADDIToFold should be the global TLS address // (the local-exec TLS variable). We only perform the folding if the TLS // variable is the second operand. - SDValue TLSVarNode = ADDIToFold.getOperand(1); GlobalAddressSDNode *GA = dyn_cast(TLSVarNode); if (!GA) return false; @@ -7649,7 +7664,6 @@ static void foldADDIForLocalExecAccesses(SDNode *N, SelectionDAG *DAG) { void PPCDAGToDAGISel::PeepholePPC64() { SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end(); - bool HasAIXSmallLocalExecTLS = Subtarget->hasAIXSmallLocalExecTLS(); while (Position != CurDAG->allnodes_begin()) { SDNode *N = &*--Position; @@ -7661,8 +7675,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { reduceVSXSwap(N, CurDAG); // This optimization is performed for non-TOC-based local-exec accesses. - if (HasAIXSmallLocalExecTLS) - foldADDIForLocalExecAccesses(N, CurDAG); + foldADDIForLocalExecAccesses(N, CurDAG); unsigned FirstOp; unsigned StorageOpcode = N->getMachineOpcode(); @@ -7821,8 +7834,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { ImmOpnd.getValueType()); } else if (Offset != 0) { // This optimization is performed for non-TOC-based local-exec accesses. - if (HasAIXSmallLocalExecTLS && - isEligibleToFoldADDIForLocalExecAccesses(CurDAG, Base)) { + if (isEligibleToFoldADDIForLocalExecAccesses(CurDAG, Base)) { // Add the non-zero offset information into the load or store // instruction to be used for non-TOC-based local-exec accesses. GlobalAddressSDNode *GA = dyn_cast(ImmOpnd); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index cce0efad39c7..7436b202fba0 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -3367,15 +3367,21 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, const GlobalValue *GV = GA->getGlobal(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); bool Is64Bit = Subtarget.isPPC64(); - bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS(); TLSModel::Model Model = getTargetMachine().getTLSModel(GV); bool IsTLSLocalExecModel = Model == TLSModel::LocalExec; if (IsTLSLocalExecModel || Model == TLSModel::InitialExec) { + bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS(); + bool HasAIXSmallTLSGlobalAttr = false; SDValue VariableOffsetTGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TPREL_FLAG); SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA); SDValue TLSReg; + + if (const GlobalVariable *GVar = dyn_cast(GV)) + if (GVar->hasAttribute("aix-small-tls")) + HasAIXSmallTLSGlobalAttr = true; + if (Is64Bit) { // For local-exec and initial-exec on AIX (64-bit), the sequence generated // involves a load of the variable offset (from the TOC), followed by an @@ -3385,14 +3391,16 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, // add reg2, reg1, r13 // r13 contains the thread pointer TLSReg = DAG.getRegister(PPC::X13, MVT::i64); - // With the -maix-small-local-exec-tls option, produce a faster access - // sequence for local-exec TLS variables where the offset from the TLS - // base is encoded as an immediate operand. + // With the -maix-small-local-exec-tls option, or with the "aix-small-tls" + // global variable attribute, produce a faster access sequence for + // local-exec TLS variables where the offset from the TLS base is encoded + // as an immediate operand. // // We only utilize the faster local-exec access sequence when the TLS // variable has a size within the policy limit. We treat types that are // not sized or are empty as being over the policy size limit. - if (HasAIXSmallLocalExecTLS && IsTLSLocalExecModel) { + if ((HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) && + IsTLSLocalExecModel) { Type *GVType = GV->getValueType(); if (GVType->isSized() && !GVType->isEmptyTy() && GV->getParent()->getDataLayout().getTypeAllocSize(GVType) <= @@ -3410,8 +3418,9 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, TLSReg = DAG.getNode(PPCISD::GET_TPOINTER, dl, PtrVT); // We do not implement the 32-bit version of the faster access sequence - // for local-exec that is controlled by -maix-small-local-exec-tls. - if (HasAIXSmallLocalExecTLS) + // for local-exec that is controlled by the -maix-small-local-exec-tls + // option, or the "aix-small-tls" global variable attribute. + if (HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) report_fatal_error("The small-local-exec TLS access sequence is " "currently only supported on AIX (64-bit mode)."); } diff --git a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll new file mode 100644 index 000000000000..38b35dc6c81c --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll @@ -0,0 +1,105 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: | FileCheck %s --check-prefixes=COMMONCM,CHECK-SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: < %s | FileCheck %s --check-prefixes=COMMONCM,CHECK-LARGECM64 + +@mySmallTLS = thread_local(localexec) global [7800 x i64] zeroinitializer, align 8 #0 +@mySmallTLS2 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 #0 +@mySmallTLS3 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +; All accesses use a "faster" local-exec sequence directly off the thread pointer, +; except for mySmallTLS, as this variable is over the 32KB size limit. +define i64 @StoreLargeAccess1() #1 { +; COMMONCM-LABEL: StoreLargeAccess1: +; COMMONCM-NEXT: # %bb.0: # %entry +; CHECK-SMALLCM64: ld r3, L..C0(r2) # target-flags(ppc-tprel) @mySmallTLS +; CHECK-SMALLCM64-NEXT: li r4, 0 +; CHECK-SMALLCM64-NEXT: li r5, 23 +; CHECK-LARGECM64: addis r3, L..C0@u(r2) +; CHECK-LARGECM64-NEXT: li r4, 0 +; CHECK-LARGECM64-NEXT: li r5, 23 +; CHECK-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; COMMONCM: ori r4, r4, 53328 +; COMMONCM-NEXT: add r3, r13, r3 +; COMMONCM-NEXT: stdx r5, r3, r4 +; COMMONCM-NEXT: li r3, 55 +; COMMONCM-NEXT: li r4, 64 +; COMMONCM-NEXT: std r3, (mySmallTLS2[TL]@le+696)-65536(r13) +; COMMONCM-NEXT: li r3, 142 +; COMMONCM-NEXT: std r4, (mySmallTLS3[TL]@le+20000)-131072(r13) +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS) + %arrayidx = getelementptr inbounds i8, ptr %tls0, i32 53328 + store i64 23, ptr %arrayidx, align 8 + %tls1 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS2) + %arrayidx1 = getelementptr inbounds i8, ptr %tls1, i32 696 + store i64 55, ptr %arrayidx1, align 8 + %tls2 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS3) + %arrayidx2 = getelementptr inbounds i8, ptr %tls2, i32 20000 + store i64 64, ptr %arrayidx2, align 8 + %load1 = load i64, ptr %arrayidx, align 8 + %load2 = load i64, ptr %arrayidx1, align 8 + %add1 = add i64 %load1, 64 + %add2 = add i64 %add1, %load2 + ret i64 %add2 +} + +; Since this function does not have the 'aix-small-local-exec-tls` attribute, +; only some local-exec variables should have the small-local-exec TLS access +; sequence (as opposed to all of them). +define i64 @StoreLargeAccess2() { +; COMMONCM-LABEL: StoreLargeAccess2: +; COMMONCM-NEXT: # %bb.0: # %entry +; CHECK-SMALLCM64: ld r5, L..C0(r2) # target-flags(ppc-tprel) @mySmallTLS +; CHECK-SMALLCM64-NEXT: li r3, 0 +; CHECK-SMALLCM64-NEXT: li r4, 23 +; CHECK-SMALLCM64-NEXT: ori r3, r3, 53328 +; CHECK-SMALLCM64-NEXT: add r5, r13, r5 +; CHECK-SMALLCM64-NEXT: stdx r4, r5, r3 +; CHECK-SMALLCM64-NEXT: ld r5, L..C1(r2) # target-flags(ppc-tprel) @mySmallTLS3 +; CHECK-SMALLCM64-NEXT: li r3, 55 +; CHECK-SMALLCM64-NEXT: li r4, 64 +; CHECK-SMALLCM64-NEXT: std r3, mySmallTLS2[TL]@le+696(r13) +; CHECK-SMALLCM64-NEXT: li r3, 142 +; CHECK-SMALLCM64-NEXT: add r5, r13, r5 +; CHECK-SMALLCM64-NEXT: std r4, 20000(r5) +; CHECK-LARGECM64: addis r3, L..C0@u(r2) +; CHECK-LARGECM64-NEXT: li r4, 0 +; CHECK-LARGECM64-NEXT: li r5, 23 +; CHECK-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; CHECK-LARGECM64-NEXT: ori r4, r4, 53328 +; CHECK-LARGECM64-NEXT: add r3, r13, r3 +; CHECK-LARGECM64-NEXT: stdx r5, r3, r4 +; CHECK-LARGECM64-NEXT: addis r3, L..C1@u(r2) +; CHECK-LARGECM64-NEXT: li r4, 55 +; CHECK-LARGECM64-NEXT: li r5, 64 +; CHECK-LARGECM64-NEXT: ld r3, L..C1@l(r3) +; CHECK-LARGECM64-NEXT: std r4, mySmallTLS2[TL]@le+696(r13) +; CHECK-LARGECM64-NEXT: add r3, r13, r3 +; CHECK-LARGECM64-NEXT: std r5, 20000(r3) +; CHECK-LARGECM64-NEXT: li r3, 142 +; COMMONCM-NEXT: blr +; +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS) + %arrayidx = getelementptr inbounds i8, ptr %tls0, i32 53328 + store i64 23, ptr %arrayidx, align 8 + %tls1 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS2) + %arrayidx1 = getelementptr inbounds i8, ptr %tls1, i32 696 + store i64 55, ptr %arrayidx1, align 8 + %tls2 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS3) + %arrayidx2 = getelementptr inbounds i8, ptr %tls2, i32 20000 + store i64 64, ptr %arrayidx2, align 8 + %load1 = load i64, ptr %arrayidx, align 8 + %load2 = load i64, ptr %arrayidx1, align 8 + %add1 = add i64 %load1, 64 + %add2 = add i64 %add1, %load2 + ret i64 %add2 +} + +attributes #0 = { "aix-small-tls" } +attributes #1 = { "target-features"="+aix-small-local-exec-tls" } diff --git a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-loadaddr.ll b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-loadaddr.ll new file mode 100644 index 000000000000..c8537fba6a3c --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-loadaddr.ll @@ -0,0 +1,222 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff -mattr=-aix-small-local-exec-tls \ +; RUN: < %s | FileCheck %s --check-prefixes=COMMONCM,SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: -mattr=-aix-small-local-exec-tls < %s | \ +; RUN: FileCheck %s --check-prefixes=COMMONCM,LARGECM64 + +; Test that the 'aix-small-tls' global variable attribute generates the +; optimized small-local-exec TLS sequence. Global variables without this +; attribute should still generate a TOC-based local-exec access sequence. + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +@a = thread_local(localexec) global [87 x i8] zeroinitializer, align 1 #0 +@a_noattr = thread_local(localexec) global [87 x i8] zeroinitializer, align 1 +@b = thread_local(localexec) global [87 x i16] zeroinitializer, align 2 #0 +@b_noattr = thread_local(localexec) global [87 x i16] zeroinitializer, align 2 +@c = thread_local(localexec) global [87 x i32] zeroinitializer, align 4 #0 +@c_noattr = thread_local(localexec) global [87 x i32] zeroinitializer, align 4 +@d = thread_local(localexec) global [87 x i64] zeroinitializer, align 8 #0 +@d_noattr = thread_local(localexec) global [87 x i64] zeroinitializer, align 8 #0 + +@e = thread_local(localexec) global [87 x double] zeroinitializer, align 8 #0 +@e_noattr = thread_local(localexec) global [87 x double] zeroinitializer, align 8 +@f = thread_local(localexec) global [87 x float] zeroinitializer, align 4 #0 +@f_noattr = thread_local(localexec) global [87 x float] zeroinitializer, align 4 + +define nonnull ptr @AddrTest1() { +; COMMONCM-LABEL: AddrTest1: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, a[TL]@le+1 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @a) + %arrayidx = getelementptr inbounds [87 x i8], ptr %tls0, i64 0, i64 1 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest1_NoAttr() { +; SMALLCM64-LABEL: AddrTest1_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @a_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 1 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest1_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C0@u(r2) +; LARGECM64-NEXT: ld r3, L..C0@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 1 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @a_noattr) + %arrayidx = getelementptr inbounds [87 x i8], ptr %tls0, i64 0, i64 1 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest2() { +; COMMONCM-LABEL: AddrTest2: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, b[TL]@le+4 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 2 ptr @llvm.threadlocal.address.p0(ptr align 2 @b) + %arrayidx = getelementptr inbounds [87 x i16], ptr %tls0, i64 0, i64 2 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest2_NoAttr() { +; SMALLCM64-LABEL: AddrTest2_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @b_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 4 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest2_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C1@u(r2) +; LARGECM64-NEXT: ld r3, L..C1@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 4 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 2 ptr @llvm.threadlocal.address.p0(ptr align 2 @b_noattr) + %arrayidx = getelementptr inbounds [87 x i16], ptr %tls0, i64 0, i64 2 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest3() { +; COMMONCM-LABEL: AddrTest3: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, c[TL]@le+12 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @c) + %arrayidx = getelementptr inbounds [87 x i32], ptr %tls0, i64 0, i64 3 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest3_NoAttr() { +; SMALLCM64-LABEL: AddrTest3_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @c_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 12 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest3_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C2@u(r2) +; LARGECM64-NEXT: ld r3, L..C2@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 12 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @c_noattr) + %arrayidx = getelementptr inbounds [87 x i32], ptr %tls0, i64 0, i64 3 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest4() { +; COMMONCM-LABEL: AddrTest4: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, c[TL]@le+56 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @c) + %arrayidx = getelementptr inbounds [87 x i64], ptr %tls0, i64 0, i64 7 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest4_NoAttr() { +; SMALLCM64-LABEL: AddrTest4_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @c_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 56 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest4_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C2@u(r2) +; LARGECM64-NEXT: ld r3, L..C2@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 56 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @c_noattr) + %arrayidx = getelementptr inbounds [87 x i64], ptr %tls0, i64 0, i64 7 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest5() { +; COMMONCM-LABEL: AddrTest5: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, e[TL]@le+48 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @e) + %arrayidx = getelementptr inbounds [87 x double], ptr %tls0, i64 0, i64 6 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest5_NoAttr() { +; SMALLCM64-LABEL: AddrTest5_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @e_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 48 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest5_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C3@u(r2) +; LARGECM64-NEXT: ld r3, L..C3@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 48 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @e_noattr) + %arrayidx = getelementptr inbounds [87 x double], ptr %tls0, i64 0, i64 6 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest6() { +; COMMONCM-LABEL: AddrTest6: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, f[TL]@le+16 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @f) + %arrayidx = getelementptr inbounds [87 x float], ptr %tls0, i64 0, i64 4 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest6_NoAttr() { +; SMALLCM64-LABEL: AddrTest6_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C4(r2) # target-flags(ppc-tprel) @f_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 16 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest6_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C4@u(r2) +; LARGECM64-NEXT: ld r3, L..C4@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 16 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @f_noattr) + %arrayidx = getelementptr inbounds [87 x float], ptr %tls0, i64 0, i64 4 + ret ptr %arrayidx +} + +attributes #0 = { "aix-small-tls" } diff --git a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-targetattr.ll b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-targetattr.ll new file mode 100644 index 000000000000..1e4a3b9bcc47 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-targetattr.ll @@ -0,0 +1,53 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff -mattr=+aix-small-local-exec-tls < %s \ +; RUN: | FileCheck %s --check-prefixes=COMMONCM,SMALL-LOCAL-EXEC-SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: -mattr=+aix-small-local-exec-tls < %s | FileCheck %s \ +; RUN: --check-prefixes=COMMONCM,SMALL-LOCAL-EXEC-LARGECM64 + +@mySmallTLS = thread_local(localexec) global [7800 x i64] zeroinitializer, align 8 #0 +@mySmallTLS2 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 #0 +@mySmallTLS3 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +; Although some global variables are annotated with 'aix-small-tls', because the +; aix-small-local-exec-tls target attribute is turned on, all accesses will use +; a "faster" local-exec sequence directly off the thread pointer. +define i64 @StoreLargeAccess1() { +; COMMONCM-LABEL: StoreLargeAccess1: +; COMMONCM-NEXT: # %bb.0: # %entry +; SMALL-LOCAL-EXEC-SMALLCM64: ld r3, L..C0(r2) # target-flags(ppc-tprel) @mySmallTLS +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r4, 0 +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r5, 23 +; SMALL-LOCAL-EXEC-LARGECM64: addis r3, L..C0@u(r2) +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r4, 0 +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r5, 23 +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; COMMONCM: ori r4, r4, 53328 +; COMMONCM-NEXT: add r3, r13, r3 +; COMMONCM-NEXT: stdx r5, r3, r4 +; COMMONCM-NEXT: li r3, 55 +; COMMONCM-NEXT: li r4, 64 +; COMMONCM-NEXT: std r3, (mySmallTLS2[TL]@le+696)-65536(r13) +; COMMONCM-NEXT: li r3, 142 +; COMMONCM-NEXT: std r4, (mySmallTLS3[TL]@le+20000)-131072(r13) +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS) + %arrayidx = getelementptr inbounds i8, ptr %tls0, i32 53328 + store i64 23, ptr %arrayidx, align 8 + %tls1 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS2) + %arrayidx1 = getelementptr inbounds i8, ptr %tls1, i32 696 + store i64 55, ptr %arrayidx1, align 8 + %tls2 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS3) + %arrayidx2 = getelementptr inbounds i8, ptr %tls2, i32 20000 + store i64 64, ptr %arrayidx2, align 8 + %load1 = load i64, ptr %arrayidx, align 8 + %load2 = load i64, ptr %arrayidx1, align 8 + %add1 = add i64 %load1, 64 + %add2 = add i64 %add1, %load2 + ret i64 %add2 +} + +attributes #0 = { "aix-small-tls" } -- GitLab From 84780af4b02cb3b86e4cb724f996bf8e02f2f2e7 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Thu, 28 Mar 2024 06:54:36 -0700 Subject: [PATCH 198/541] [CodeGen][arm64e] Add methods and data members to Address, which are needed to authenticate signed pointers (#86923) To authenticate pointers, CodeGen needs access to the key and discriminators that were used to sign the pointer. That information is sometimes known from the context, but not always, which is why `Address` needs to hold that information. This patch adds methods and data members to `Address`, which will be needed in subsequent patches to authenticate signed pointers, and uses the newly added methods throughout CodeGen. Although this patch isn't strictly NFC as it causes CodeGen to use different code paths in some cases (e.g., `mergeAddressesInConditionalExpr`), it doesn't cause any changes in functionality as it doesn't add any information needed for authentication. In addition to the changes mentioned above, this patch introduces class `RawAddress`, which contains a pointer that we know is unsigned, and adds several new functions for creating `Address` and `LValue` objects. This reapplies d9a685a9dd589486e882b722e513ee7b8c84870c, which was reverted because it broke ubsan bots. There seems to be a bug in coroutine code-gen, which is causing EmitTypeCheck to use the wrong alignment. For now, pass alignment zero to EmitTypeCheck so that it can compute the correct alignment based on the passed type (see function EmitCXXMemberOrOperatorMemberCallExpr). --- clang/lib/CodeGen/ABIInfoImpl.cpp | 10 +- clang/lib/CodeGen/Address.h | 195 ++++++++++++++--- clang/lib/CodeGen/CGAtomic.cpp | 53 ++--- clang/lib/CodeGen/CGBlocks.cpp | 34 +-- clang/lib/CodeGen/CGBlocks.h | 3 +- clang/lib/CodeGen/CGBuilder.h | 234 ++++++++++++++------- clang/lib/CodeGen/CGBuiltin.cpp | 173 +++++++-------- clang/lib/CodeGen/CGCUDANV.cpp | 19 +- clang/lib/CodeGen/CGCXXABI.cpp | 21 +- clang/lib/CodeGen/CGCXXABI.h | 14 +- clang/lib/CodeGen/CGCall.cpp | 171 ++++++++------- clang/lib/CodeGen/CGCall.h | 1 + clang/lib/CodeGen/CGClass.cpp | 76 ++++--- clang/lib/CodeGen/CGCleanup.cpp | 110 ++++------ clang/lib/CodeGen/CGCleanup.h | 2 +- clang/lib/CodeGen/CGCoroutine.cpp | 4 +- clang/lib/CodeGen/CGDecl.cpp | 28 +-- clang/lib/CodeGen/CGException.cpp | 19 +- clang/lib/CodeGen/CGExpr.cpp | 227 ++++++++++---------- clang/lib/CodeGen/CGExprAgg.cpp | 29 +-- clang/lib/CodeGen/CGExprCXX.cpp | 115 +++++----- clang/lib/CodeGen/CGExprConstant.cpp | 4 +- clang/lib/CodeGen/CGExprScalar.cpp | 23 +- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 8 +- clang/lib/CodeGen/CGObjC.cpp | 43 ++-- clang/lib/CodeGen/CGObjCGNU.cpp | 42 ++-- clang/lib/CodeGen/CGObjCMac.cpp | 95 ++++----- clang/lib/CodeGen/CGObjCRuntime.cpp | 6 +- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 194 +++++++++-------- clang/lib/CodeGen/CGOpenMPRuntime.h | 5 +- clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 76 +++---- clang/lib/CodeGen/CGStmt.cpp | 8 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 87 ++++---- clang/lib/CodeGen/CGVTables.cpp | 9 +- clang/lib/CodeGen/CGValue.h | 250 +++++++++++----------- clang/lib/CodeGen/CodeGenFunction.cpp | 71 ++++--- clang/lib/CodeGen/CodeGenFunction.h | 257 ++++++++++++++++------- clang/lib/CodeGen/CodeGenModule.cpp | 2 +- clang/lib/CodeGen/CodeGenPGO.cpp | 10 +- clang/lib/CodeGen/CodeGenPGO.h | 6 +- clang/lib/CodeGen/ItaniumCXXABI.cpp | 52 ++--- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 58 ++--- clang/lib/CodeGen/TargetInfo.h | 5 + clang/lib/CodeGen/Targets/NVPTX.cpp | 2 +- clang/lib/CodeGen/Targets/PPC.cpp | 11 +- clang/lib/CodeGen/Targets/Sparc.cpp | 2 +- clang/lib/CodeGen/Targets/SystemZ.cpp | 9 +- clang/lib/CodeGen/Targets/XCore.cpp | 2 +- clang/utils/TableGen/MveEmitter.cpp | 2 +- llvm/include/llvm/IR/IRBuilder.h | 1 + 50 files changed, 1644 insertions(+), 1234 deletions(-) diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index dd59101ecc81..3e34d82cb399 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -187,7 +187,7 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits FullDirectSize = DirectSize.alignTo(SlotSize); Address NextPtr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next"); - CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); // If the argument is smaller than a slot, and this is a big-endian // target, the argument will be right-adjusted in its slot. @@ -239,8 +239,8 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, const llvm::Twine &Name) { assert(Addr1.getType() == Addr2.getType()); llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name); - PHI->addIncoming(Addr1.getPointer(), Block1); - PHI->addIncoming(Addr2.getPointer(), Block2); + PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1); + PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2); CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment()); return Address(PHI, Addr1.getElementType(), Align); } @@ -400,7 +400,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty); llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy); llvm::Value *Addr = - CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy); + CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy); return Address(Addr, ElementTy, TyAlignForABI); } else { assert((AI.isDirect() || AI.isExtend()) && @@ -416,7 +416,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!"); Address Temp = CGF.CreateMemTemp(Ty, "varet"); - Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(), + Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Ty)); CGF.Builder.CreateStore(Val, Temp); return Temp; diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index cf48df8f5e73..35ec370a139c 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #include "clang/AST/CharUnits.h" +#include "clang/AST/Type.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Constants.h" #include "llvm/Support/MathExtras.h" @@ -22,28 +23,41 @@ namespace clang { namespace CodeGen { +class Address; +class CGBuilderTy; +class CodeGenFunction; +class CodeGenModule; + // Indicates whether a pointer is known not to be null. enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; -/// An aligned address. -class Address { +/// An abstract representation of an aligned address. This is designed to be an +/// IR-level abstraction, carrying just the information necessary to perform IR +/// operations on an address like loads and stores. In particular, it doesn't +/// carry C type information or allow the representation of things like +/// bit-fields; clients working at that level should generally be using +/// `LValue`. +/// The pointer contained in this class is known to be unsigned. +class RawAddress { llvm::PointerIntPair PointerAndKnownNonNull; llvm::Type *ElementType; CharUnits Alignment; protected: - Address(std::nullptr_t) : ElementType(nullptr) {} + RawAddress(std::nullptr_t) : ElementType(nullptr) {} public: - Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, - KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) : PointerAndKnownNonNull(Pointer, IsKnownNonNull), ElementType(ElementType), Alignment(Alignment) { assert(Pointer != nullptr && "Pointer cannot be null"); assert(ElementType != nullptr && "Element type cannot be null"); } - static Address invalid() { return Address(nullptr); } + inline RawAddress(Address Addr); + + static RawAddress invalid() { return RawAddress(nullptr); } bool isValid() const { return PointerAndKnownNonNull.getPointer() != nullptr; } @@ -80,6 +94,133 @@ public: return Alignment; } + /// Return address with different element type, but same pointer and + /// alignment. + RawAddress withElementType(llvm::Type *ElemTy) const { + return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); + } + + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); + } +}; + +/// Like RawAddress, an abstract representation of an aligned address, but the +/// pointer contained in this class is possibly signed. +class Address { + friend class CGBuilderTy; + + // The boolean flag indicates whether the pointer is known to be non-null. + llvm::PointerIntPair Pointer; + + /// The expected IR type of the pointer. Carrying accurate element type + /// information in Address makes it more convenient to work with Address + /// values and allows frontend assertions to catch simple mistakes. + llvm::Type *ElementType = nullptr; + + CharUnits Alignment; + + /// Offset from the base pointer. + llvm::Value *Offset = nullptr; + + llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const; + +protected: + Address(std::nullptr_t) : ElementType(nullptr) {} + +public: + Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(pointer, IsKnownNonNull), ElementType(elementType), + Alignment(alignment) { + assert(pointer != nullptr && "Pointer cannot be null"); + assert(elementType != nullptr && "Element type cannot be null"); + assert(!alignment.isZero() && "Alignment cannot be zero"); + } + + Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment, + llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType), + Alignment(Alignment), Offset(Offset) {} + + Address(RawAddress RawAddr) + : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr), + ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr), + Alignment(RawAddr.isValid() ? RawAddr.getAlignment() + : CharUnits::Zero()) {} + + static Address invalid() { return Address(nullptr); } + bool isValid() const { return Pointer.getPointer() != nullptr; } + + /// This function is used in situations where the caller is doing some sort of + /// opaque "laundering" of the pointer. + void replaceBasePointer(llvm::Value *P) { + assert(isValid() && "pointer isn't valid"); + assert(P->getType() == Pointer.getPointer()->getType() && + "Pointer's type changed"); + Pointer.setPointer(P); + assert(isValid() && "pointer is invalid after replacement"); + } + + CharUnits getAlignment() const { return Alignment; } + + void setAlignment(CharUnits Value) { Alignment = Value; } + + llvm::Value *getBasePointer() const { + assert(isValid() && "pointer isn't valid"); + return Pointer.getPointer(); + } + + /// Return the type of the pointer value. + llvm::PointerType *getType() const { + return llvm::PointerType::get( + ElementType, + llvm::cast(Pointer.getPointer()->getType()) + ->getAddressSpace()); + } + + /// Return the type of the values stored in this address. + llvm::Type *getElementType() const { + assert(isValid()); + return ElementType; + } + + /// Return the address space that this address resides in. + unsigned getAddressSpace() const { return getType()->getAddressSpace(); } + + /// Return the IR name of the pointer value. + llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } + + // This function is called only in CGBuilderBaseTy::CreateElementBitCast. + void setElementType(llvm::Type *Ty) { + assert(hasOffset() && + "this funcion shouldn't be called when there is no offset"); + ElementType = Ty; + } + + /// Whether the pointer is known not to be null. + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)Pointer.getInt(); + } + + Address setKnownNonNull() { + assert(isValid()); + Pointer.setInt(KnownNonNull); + return *this; + } + + bool hasOffset() const { return Offset; } + + llvm::Value *getOffset() const { return Offset; } + + /// Return the pointer contained in this class after authenticating it and + /// adding offset to it if necessary. + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return getBasePointer(); + } + /// Return address with different pointer, but same element type and /// alignment. Address withPointer(llvm::Value *NewPointer, @@ -91,61 +232,59 @@ public: /// Return address with different alignment, but same pointer and element /// type. Address withAlignment(CharUnits NewAlignment) const { - return Address(getPointer(), getElementType(), NewAlignment, + return Address(Pointer.getPointer(), getElementType(), NewAlignment, isKnownNonNull()); } /// Return address with different element type, but same pointer and /// alignment. Address withElementType(llvm::Type *ElemTy) const { - return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); - } - - /// Whether the pointer is known not to be null. - KnownNonNull_t isKnownNonNull() const { - assert(isValid()); - return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); - } - - /// Set the non-null bit. - Address setKnownNonNull() { - assert(isValid()); - PointerAndKnownNonNull.setInt(true); - return *this; + if (!hasOffset()) + return Address(getBasePointer(), ElemTy, getAlignment(), nullptr, + isKnownNonNull()); + Address A(*this); + A.ElementType = ElemTy; + return A; } }; +inline RawAddress::RawAddress(Address Addr) + : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, + Addr.isValid() ? Addr.isKnownNonNull() + : NotKnownNonNull), + ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), + Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} + /// A specialization of Address that requires the address to be an /// LLVM Constant. -class ConstantAddress : public Address { - ConstantAddress(std::nullptr_t) : Address(nullptr) {} +class ConstantAddress : public RawAddress { + ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {} public: ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, CharUnits alignment) - : Address(pointer, elementType, alignment) {} + : RawAddress(pointer, elementType, alignment) {} static ConstantAddress invalid() { return ConstantAddress(nullptr); } llvm::Constant *getPointer() const { - return llvm::cast(Address::getPointer()); + return llvm::cast(RawAddress::getPointer()); } ConstantAddress withElementType(llvm::Type *ElemTy) const { return ConstantAddress(getPointer(), ElemTy, getAlignment()); } - static bool isaImpl(Address addr) { + static bool isaImpl(RawAddress addr) { return llvm::isa(addr.getPointer()); } - static ConstantAddress castImpl(Address addr) { + static ConstantAddress castImpl(RawAddress addr) { return ConstantAddress(llvm::cast(addr.getPointer()), addr.getElementType(), addr.getAlignment()); } }; - } // Present a minimal LLVM-like casting interface. diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index fb03d013e8af..56198385de9d 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -80,7 +80,7 @@ namespace { AtomicSizeInBits = C.toBits( C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1) .alignTo(lvalue.getAlignment())); - llvm::Value *BitFieldPtr = lvalue.getBitFieldPointer(); + llvm::Value *BitFieldPtr = lvalue.getRawBitFieldPointer(CGF); auto OffsetInChars = (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) * lvalue.getAlignment(); @@ -139,13 +139,13 @@ namespace { const LValue &getAtomicLValue() const { return LVal; } llvm::Value *getAtomicPointer() const { if (LVal.isSimple()) - return LVal.getPointer(CGF); + return LVal.emitRawPointer(CGF); else if (LVal.isBitField()) - return LVal.getBitFieldPointer(); + return LVal.getRawBitFieldPointer(CGF); else if (LVal.isVectorElt()) - return LVal.getVectorPointer(); + return LVal.getRawVectorPointer(CGF); assert(LVal.isExtVectorElt()); - return LVal.getExtVectorPointer(); + return LVal.getRawExtVectorPointer(CGF); } Address getAtomicAddress() const { llvm::Type *ElTy; @@ -368,7 +368,7 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const { return false; CGF.Builder.CreateMemSet( - addr.getPointer(), llvm::ConstantInt::get(CGF.Int8Ty, 0), + addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0), CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(), LVal.getAlignment().getAsAlign()); return true; @@ -1055,7 +1055,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { return getTargetHooks().performAddrSpaceCast( *this, V, AS, LangAS::opencl_generic, DestType, false); }; - Args.add(RValue::get(CastToGenericAddrSpace(Ptr.getPointer(), + + Args.add(RValue::get(CastToGenericAddrSpace(Ptr.emitRawPointer(*this), E->getPtr()->getType())), getContext().VoidPtrTy); @@ -1086,10 +1087,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_compare_exchange"; RetTy = getContext().BoolTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); - Args.add(RValue::get(CastToGenericAddrSpace(Val2.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val2.emitRawPointer(*this), E->getVal2()->getType())), getContext().VoidPtrTy); Args.add(RValue::get(Order), getContext().IntTy); @@ -1105,7 +1106,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__scoped_atomic_exchange: case AtomicExpr::AO__scoped_atomic_exchange_n: LibCallName = "__atomic_exchange"; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1120,7 +1121,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_store"; RetTy = getContext().VoidTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1199,7 +1200,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { if (!HaveRetTy) { // Value is returned through parameter before the order. RetTy = getContext().VoidTy; - Args.add(RValue::get(CastToGenericAddrSpace(Dest.getPointer(), RetTy)), + Args.add(RValue::get( + CastToGenericAddrSpace(Dest.emitRawPointer(*this), RetTy)), getContext().VoidPtrTy); } // Order is always the last parameter. @@ -1513,7 +1515,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } else TempAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(TempAddr.emitRawPointer(CGF), AO, IsVolatile); // Okay, turn that back into the original value or whole atomic (for // non-simple lvalues) type. @@ -1673,9 +1675,9 @@ std::pair AtomicInfo::EmitAtomicCompareExchange( if (shouldUseLibcall()) { // Produce a source address. Address ExpectedAddr = materializeRValue(Expected); - Address DesiredAddr = materializeRValue(Desired); - auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF); + auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, Success, Failure); return std::make_pair( convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(), @@ -1757,7 +1759,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall( Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1771,10 +1773,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall( AggValueSlot::ignored(), SourceLocation(), /*AsValue=*/false); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1843,7 +1845,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1854,10 +1856,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, CGF.Builder.CreateStore(OldVal, DesiredAddr); } EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1957,7 +1959,8 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(atomics.getAtomicPointer()), getContext().VoidPtrTy); - args.add(RValue::get(srcAddr.getPointer()), getContext().VoidPtrTy); + args.add(RValue::get(srcAddr.emitRawPointer(*this)), + getContext().VoidPtrTy); args.add( RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))), getContext().IntTy); diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index ad0b50d79961..a01f2c7c9798 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -36,7 +36,8 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), NoEscape(false), HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), CapturesNonExternalType(false), - LocalAddress(Address::invalid()), StructureType(nullptr), Block(block) { + LocalAddress(RawAddress::invalid()), StructureType(nullptr), + Block(block) { // Skip asm prefix, if any. 'name' is usually taken directly from // the mangled name of the enclosing function. @@ -794,7 +795,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // Otherwise, we have to emit this as a local block. - Address blockAddr = blockInfo.LocalAddress; + RawAddress blockAddr = blockInfo.LocalAddress; assert(blockAddr.isValid() && "block has no address!"); llvm::Constant *isa; @@ -939,7 +940,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { if (CI.isNested()) byrefPointer = Builder.CreateLoad(src, "byref.capture"); else - byrefPointer = src.getPointer(); + byrefPointer = src.emitRawPointer(*this); // Write that void* into the capture field. Builder.CreateStore(byrefPointer, blockField); @@ -961,10 +962,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { } // If it's a reference variable, copy the reference into the block field. - } else if (type->isReferenceType()) { - Builder.CreateStore(src.getPointer(), blockField); + } else if (auto refType = type->getAs()) { + Builder.CreateStore(src.emitRawPointer(*this), blockField); - // If type is const-qualified, copy the value into the block field. + // If type is const-qualified, copy the value into the block field. } else if (type.isConstQualified() && type.getObjCLifetime() == Qualifiers::OCL_Strong && CGM.getCodeGenOpts().OptimizationLevel != 0) { @@ -1377,7 +1378,7 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, // Allocate a stack slot like for any local variable to guarantee optimal // debug info at -O0. The mem2reg pass will eliminate it when optimizing. - Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); + RawAddress alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); Builder.CreateStore(arg, alloc); if (CGDebugInfo *DI = getDebugInfo()) { if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { @@ -1497,7 +1498,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( // frame setup instruction by llvm::DwarfDebug::beginFunction(). auto NL = ApplyDebugLocation::CreateEmpty(*this); Builder.CreateStore(BlockPointer, Alloca); - BlockPointerDbgLoc = Alloca.getPointer(); + BlockPointerDbgLoc = Alloca.emitRawPointer(*this); } // If we have a C++ 'this' reference, go ahead and force it into @@ -1557,8 +1558,8 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); if (capture.isConstant()) { auto addr = LocalDeclMap.find(variable)->second; - (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), - Builder); + (void)DI->EmitDeclareOfAutoVariable( + variable, addr.emitRawPointer(*this), Builder); continue; } @@ -1662,7 +1663,7 @@ struct CallBlockRelease final : EHScopeStack::Cleanup { if (LoadBlockVarAddr) { BlockVarAddr = CGF.Builder.CreateLoad(Addr); } else { - BlockVarAddr = Addr.getPointer(); + BlockVarAddr = Addr.emitRawPointer(CGF); } CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow); @@ -1962,13 +1963,15 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - cast(dstField.getPointer())->eraseFromParent(); + if (auto *I = + cast_or_null(dstField.getBasePointer())) + I->eraseFromParent(); } break; } case BlockCaptureEntityKind::BlockObject: { llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - llvm::Value *dstAddr = dstField.getPointer(); + llvm::Value *dstAddr = dstField.emitRawPointer(*this); llvm::Value *args[] = { dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) }; @@ -2139,7 +2142,7 @@ public: llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign(); - llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal }; + llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2696,7 +2699,8 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { storeHeaderField(V, getPointerSize(), "byref.isa"); // Store the address of the variable into its own forwarding pointer. - storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding"); + storeHeaderField(addr.emitRawPointer(*this), getPointerSize(), + "byref.forwarding"); // Blocks ABI: // c) the flags field is set to either 0 if no helper functions are diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index 4ef1ae9f3365..8d10c4f69b20 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -271,7 +271,8 @@ public: /// The block's captures. Non-constant captures are sorted by their offsets. llvm::SmallVector SortedCaptures; - Address LocalAddress; + // Currently we assume that block-pointer types are never signed. + RawAddress LocalAddress; llvm::StructType *StructureType; const BlockDecl *Block; const BlockExpr *BlockExpression; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index bf5ab171d720..6dd9da7c4cad 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -10,7 +10,9 @@ #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #include "Address.h" +#include "CGValue.h" #include "CodeGenTypeCache.h" +#include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Type.h" @@ -18,12 +20,15 @@ namespace clang { namespace CodeGen { +class CGBuilderTy; class CodeGenFunction; /// This is an IRBuilder insertion helper that forwards to /// CodeGenFunction::InsertHelper, which adds necessary metadata to /// instructions. class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { + friend CGBuilderTy; + public: CGBuilderInserter() = default; explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} @@ -43,10 +48,42 @@ typedef llvm::IRBuilder CGBuilderBaseTy; class CGBuilderTy : public CGBuilderBaseTy { + friend class Address; + /// Storing a reference to the type cache here makes it a lot easier /// to build natural-feeling, target-specific IR. const CodeGenTypeCache &TypeCache; + CodeGenFunction *getCGF() const { return getInserter().CGF; } + + llvm::Value *emitRawPointerFromAddress(Address Addr) const { + return Addr.getBasePointer(); + } + + template + Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name) { + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + llvm::GetElementPtrInst *GEP; + if (IsInBounds) + GEP = cast(CreateConstInBoundsGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + else + GEP = cast(CreateConstGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + llvm::APInt Offset( + DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, + /*isSigned=*/true); + if (!GEP->accumulateConstantOffset(DL, Offset)) + llvm_unreachable("offset of GEP with constants is always computable"); + return Address(GEP, GEP->getResultElementType(), + Addr.getAlignment().alignmentAtOffset( + CharUnits::fromQuantity(Offset.getSExtValue())), + IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull); + } + public: CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) : CGBuilderBaseTy(C), TypeCache(TypeCache) {} @@ -69,20 +106,22 @@ public: // Note that we intentionally hide the CreateLoad APIs that don't // take an alignment. llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { // This overload is required to prevent string literals from // ending up in the IsVolatile overload. - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), - Addr.getAlignment().getAsAlign(), IsVolatile, - Name); + return CreateAlignedLoad( + Addr.getElementType(), emitRawPointerFromAddress(Addr), + Addr.getAlignment().getAsAlign(), IsVolatile, Name); } using CGBuilderBaseTy::CreateAlignedLoad; @@ -96,7 +135,7 @@ public: // take an alignment. llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile = false) { - return CreateAlignedStore(Val, Addr.getPointer(), + return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), IsVolatile); } @@ -132,33 +171,41 @@ public: llvm::AtomicOrdering FailureOrdering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { return CGBuilderBaseTy::CreateAtomicCmpXchg( - Addr.getPointer(), Cmp, New, Addr.getAlignment().getAsAlign(), - SuccessOrdering, FailureOrdering, SSID); + Addr.emitRawPointer(*getCGF()), Cmp, New, + Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering, + SSID); } llvm::AtomicRMWInst * CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Ordering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { - return CGBuilderBaseTy::CreateAtomicRMW(Op, Addr.getPointer(), Val, - Addr.getAlignment().getAsAlign(), - Ordering, SSID); + return CGBuilderBaseTy::CreateAtomicRMW( + Op, Addr.emitRawPointer(*getCGF()), Val, + Addr.getAlignment().getAsAlign(), Ordering, SSID); } using CGBuilderBaseTy::CreateAddrSpaceCast; Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, + llvm::Type *ElementTy, const llvm::Twine &Name = "") { - return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), - Addr.isKnownNonNull()); + if (!Addr.hasOffset()) + return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), + ElementTy, Addr.getAlignment(), nullptr, + Addr.isKnownNonNull()); + // Eagerly force a raw address if these is an offset. + return RawAddress( + CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), + ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); } using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name = "") { - llvm::Value *Ptr = - CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); - return Address(Ptr, ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); + if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace()) + return Addr.withElementType(ElementTy); + return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name); } /// Given @@ -176,10 +223,11 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address( - CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); + return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), + Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } /// Given @@ -198,7 +246,7 @@ public: CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), {getSize(CharUnits::Zero()), getSize(Index)}, Name), ElTy->getElementType(), Addr.getAlignment().alignmentAtOffset(Index * EltSize), @@ -216,10 +264,10 @@ public: const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -229,110 +277,133 @@ public: /// where i64 is actually the target word size. Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name = "") { + llvm::Type *ElTy = Addr.getElementType(); const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - CharUnits EltSize = - CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); + CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), + return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); } /// Create GEP with single dynamic index. The address alignment is reduced /// according to the element size. using CGBuilderBaseTy::CreateGEP; - Address CreateGEP(Address Addr, llvm::Value *Index, + Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name = "") { const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); return Address( - CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name), Addr.getElementType(), - Addr.getAlignment().alignmentOfArrayElement(EltSize), NotKnownNonNull); + Addr.getAlignment().alignmentOfArrayElement(EltSize)); } /// Given a pointer to i8, adjust it by a given constant offset. Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Offset), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + getSize(Offset), Name), + Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } + Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), getSize(Offset), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Offset)); } using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name = "") { - const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + return createConstGEP2_32(Addr, Idx0, Idx1, Name); + } - auto *GEP = cast(CreateConstInBoundsGEP2_32( - Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); - llvm::APInt Offset( - DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, - /*isSigned=*/true); - if (!GEP->accumulateConstantOffset(DL, Offset)) - llvm_unreachable("offset of GEP with constants is always computable"); - return Address(GEP, GEP->getResultElementType(), - Addr.getAlignment().alignmentAtOffset( - CharUnits::fromQuantity(Offset.getSExtValue())), - Addr.isKnownNonNull()); + using CGBuilderBaseTy::CreateConstGEP2_32; + Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name = "") { + return createConstGEP2_32(Addr, Idx0, Idx1, Name); + } + + Address CreateGEP(Address Addr, ArrayRef IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + llvm::Value *Ptr = emitRawPointerFromAddress(Addr); + return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name), + ElementType, Align); + } + + using CGBuilderBaseTy::CreateInBoundsGEP; + Address CreateInBoundsGEP(Address Addr, ArrayRef IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + return RawAddress(CreateInBoundsGEP(Addr.getElementType(), + emitRawPointerFromAddress(Addr), + IdxList, Name), + ElementType, Align, Addr.isKnownNonNull()); + } + + using CGBuilderBaseTy::CreateIsNull; + llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") { + if (!Addr.hasOffset()) + return CreateIsNull(Addr.getBasePointer(), Name); + // The pointer isn't null if Addr has an offset since offsets can always + // be applied inbound. + return llvm::ConstantInt::getFalse(Context); } using CGBuilderBaseTy::CreateMemCpy; llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemCpyInline; llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { - return CreateMemCpyInline( - Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), getInt64(Size)); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), getInt64(Size)); } using CGBuilderBaseTy::CreateMemMove; llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), - Size, IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemSet; llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemSet(Dest.getPointer(), Value, Size, + return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size, Dest.getAlignment().getAsAlign(), IsVolatile); } using CGBuilderBaseTy::CreateMemSetInline; llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, uint64_t Size) { - return CreateMemSetInline(Dest.getPointer(), + return CreateMemSetInline(emitRawPointerFromAddress(Dest), Dest.getAlignment().getAsAlign(), Value, getInt64(Size)); } @@ -346,16 +417,31 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), - Index, FieldIndex, DbgInfo), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset)); + return Address( + CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr), + Index, FieldIndex, DbgInfo), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + + using CGBuilderBaseTy::CreatePreserveUnionAccessIndex; + Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex, + llvm::MDNode *DbgInfo) { + Addr.replaceBasePointer(CreatePreserveUnionAccessIndex( + Addr.getBasePointer(), FieldIndex, DbgInfo)); + return Addr; } using CGBuilderBaseTy::CreateLaunderInvariantGroup; Address CreateLaunderInvariantGroup(Address Addr) { - return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()), - Addr.isKnownNonNull()); + Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer())); + return Addr; + } + + using CGBuilderBaseTy::CreateStripInvariantGroup; + Address CreateStripInvariantGroup(Address Addr) { + Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer())); + return Addr; } }; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index fdb517eb254d..5ab5917c0c8d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2117,9 +2117,9 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( auto AL = ApplyDebugLocation::CreateArtificial(*this); CharUnits Offset; - Address BufAddr = - Address(Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Int8Ty, - BufferAlignment); + Address BufAddr = makeNaturalAddressForPointer( + Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Ctx.VoidTy, + BufferAlignment); Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()), @@ -2162,7 +2162,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { // Ignore argument 1, the format string. It is not currently used. CallArgList Args; - Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy); + Args.add(RValue::get(BufAddr.emitRawPointer(*this)), Ctx.VoidPtrTy); for (const auto &Item : Layout.Items) { int Size = Item.getSizeByte(); @@ -2202,8 +2202,8 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { if (!isa(ArgVal)) { CleanupKind Cleanup = getARCCleanupKind(); QualType Ty = TheExpr->getType(); - Address Alloca = Address::invalid(); - Address Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); + RawAddress Alloca = RawAddress::invalid(); + RawAddress Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); ArgVal = EmitARCRetain(Ty, ArgVal); Builder.CreateStore(ArgVal, Addr); pushLifetimeExtendedDestroy(Cleanup, Alloca, Ty, @@ -2236,7 +2236,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( Layout, BufAddr.getAlignment()); EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); - return RValue::get(BufAddr.getPointer()); + return RValue::get(BufAddr, *this); } static bool isSpecialUnsignedMultiplySignedResult( @@ -2984,7 +2984,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Check NonnullAttribute/NullabilityArg and Alignment. auto EmitArgCheck = [&](TypeCheckKind Kind, Address A, const Expr *Arg, unsigned ParmNum) { - Value *Val = A.getPointer(); + Value *Val = A.emitRawPointer(*this); EmitNonNullArgCheck(RValue::get(Val), Arg->getType(), Arg->getExprLoc(), FD, ParmNum); @@ -3013,12 +3013,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_va_end: EmitVAStartEnd(BuiltinID == Builtin::BI__va_start ? EmitScalarExpr(E->getArg(0)) - : EmitVAListRef(E->getArg(0)).getPointer(), + : EmitVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID != Builtin::BI__builtin_va_end); return RValue::get(nullptr); case Builtin::BI__builtin_va_copy: { - Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer(); - Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer(); + Value *DstPtr = EmitVAListRef(E->getArg(0)).emitRawPointer(*this); + Value *SrcPtr = EmitVAListRef(E->getArg(1)).emitRawPointer(*this); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy, {DstPtr->getType()}), {DstPtr, SrcPtr}); return RValue::get(nullptr); @@ -3849,13 +3849,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); Address Src = EmitPointerWithAlignment(E->getArg(0)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorLoad( - Src.getElementType(), Src.getPointer(), + Src.getElementType(), Src.emitRawPointer(*this), Align(Src.getAlignment().getQuantity()), Stride, IsVolatile, - ResultTy->getNumRows(), ResultTy->getNumColumns(), - "matrix"); + ResultTy->getNumRows(), ResultTy->getNumColumns(), "matrix"); return RValue::get(Result); } @@ -3870,11 +3870,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, assert(PtrTy && "arg1 must be of pointer type"); bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); - EmitNonNullArgCheck(RValue::get(Dst.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dst.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorStore( - Matrix, Dst.getPointer(), Align(Dst.getAlignment().getQuantity()), - Stride, IsVolatile, MatrixTy->getNumRows(), MatrixTy->getNumColumns()); + Matrix, Dst.emitRawPointer(*this), + Align(Dst.getAlignment().getQuantity()), Stride, IsVolatile, + MatrixTy->getNumRows(), MatrixTy->getNumColumns()); return RValue::get(Result); } @@ -4033,7 +4035,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_bzero: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); Value *SizeVal = EmitScalarExpr(E->getArg(1)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false); return RValue::get(nullptr); @@ -4044,10 +4046,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Builder.CreateMemMove(Dest, Src, SizeVal, false); return RValue::get(nullptr); } @@ -4064,10 +4068,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateMemCpy(Dest, Src, SizeVal, false); if (BuiltinID == Builtin::BImempcpy || BuiltinID == Builtin::BI__builtin_mempcpy) - return RValue::get(Builder.CreateInBoundsGEP(Dest.getElementType(), - Dest.getPointer(), SizeVal)); + return RValue::get(Builder.CreateInBoundsGEP( + Dest.getElementType(), Dest.emitRawPointer(*this), SizeVal)); else - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memcpy_inline: { @@ -4099,7 +4103,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_objc_memmove_collectable: { @@ -4108,7 +4112,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *SizeVal = EmitScalarExpr(E->getArg(2)); CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestAddr, SrcAddr, SizeVal); - return RValue::get(DestAddr.getPointer()); + return RValue::get(DestAddr, *this); } case Builtin::BI__builtin___memmove_chk: { @@ -4125,7 +4129,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemmove: @@ -4136,7 +4140,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitArgCheck(TCK_Store, Dest, E->getArg(0), 0); EmitArgCheck(TCK_Load, Src, E->getArg(1), 1); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemset: case Builtin::BI__builtin_memset: { @@ -4144,10 +4148,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memset_inline: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); @@ -4155,8 +4159,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); uint64_t Size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Builder.CreateMemSetInline(Dest, ByteVal, Size); return RValue::get(nullptr); } @@ -4175,7 +4180,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.getInt8Ty()); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_wmemchr: { // The MSVC runtime library does not provide a definition of wmemchr, so we @@ -4397,14 +4402,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Store the stack pointer to the setjmp buffer. Value *StackAddr = Builder.CreateStackSave(); - assert(Buf.getPointer()->getType() == StackAddr->getType()); + assert(Buf.emitRawPointer(*this)->getType() == StackAddr->getType()); Address StackSaveSlot = Builder.CreateConstInBoundsGEP(Buf, 2); Builder.CreateStore(StackAddr, StackSaveSlot); // Call LLVM's EH setjmp, which is lightweight. Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); - return RValue::get(Builder.CreateCall(F, Buf.getPointer())); + return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); } case Builtin::BI__builtin_longjmp: { Value *Buf = EmitScalarExpr(E->getArg(0)); @@ -5577,7 +5582,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(2)); - llvm::Value *Range = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *Range = NDRangeL.getAddress(*this).emitRawPointer(*this); llvm::Type *RangeTy = NDRangeL.getAddress(*this).getType(); if (NumArgs == 4) { @@ -5686,9 +5691,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, getContext(), Expr::NPC_ValueDependentIsNotNull)) { EventWaitList = llvm::ConstantPointerNull::get(PtrTy); } else { - EventWaitList = E->getArg(4)->getType()->isArrayType() - ? EmitArrayToPointerDecay(E->getArg(4)).getPointer() - : EmitScalarExpr(E->getArg(4)); + EventWaitList = + E->getArg(4)->getType()->isArrayType() + ? EmitArrayToPointerDecay(E->getArg(4)).emitRawPointer(*this) + : EmitScalarExpr(E->getArg(4)); // Convert to generic address space. EventWaitList = Builder.CreatePointerCast(EventWaitList, PtrTy); } @@ -5784,7 +5790,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Type *GenericVoidPtrTy = Builder.getPtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); - llvm::Value *NDRange = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *NDRange = NDRangeL.getAddress(*this).emitRawPointer(*this); auto Info = CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); Value *Kernel = @@ -5869,7 +5875,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy0 = FTy->getParamType(0); if (PTy0 != Arg0Val->getType()) { if (Arg0Ty->isArrayType()) - Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); + Arg0Val = EmitArrayToPointerDecay(Arg0).emitRawPointer(*this); else Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); } @@ -5907,7 +5913,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy1 = FTy->getParamType(1); if (PTy1 != Arg1Val->getType()) { if (Arg1Ty->isArrayType()) - Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer(); + Arg1Val = EmitArrayToPointerDecay(Arg1).emitRawPointer(*this); else Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1); } @@ -5921,7 +5927,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_ms_va_start: case Builtin::BI__builtin_ms_va_end: return RValue::get( - EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(), + EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID == Builtin::BI__builtin_ms_va_start)); case Builtin::BI__builtin_ms_va_copy: { @@ -5963,8 +5969,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // If this is a predefined lib function (e.g. malloc), emit the call // using exactly the normal call path. if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return emitLibraryCall(*this, FD, E, - cast(EmitScalarExpr(E->getCallee()))); + return emitLibraryCall( + *this, FD, E, cast(EmitScalarExpr(E->getCallee()))); // Check that a call to a target specific builtin has the correct target // features. @@ -6081,7 +6087,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(nullptr); return RValue::get(V); case TEK_Aggregate: - return RValue::getAggregate(ReturnValue.getValue(), + return RValue::getAggregate(ReturnValue.getAddress(), ReturnValue.isVolatile()); case TEK_Complex: llvm_unreachable("No current target builtin returns complex"); @@ -8851,7 +8857,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -8878,7 +8884,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp1 = EmitPointerWithAlignment(E->getArg(1)); - Ops.push_back(PtrOp1.getPointer()); + Ops.push_back(PtrOp1.emitRawPointer(*this)); continue; } } @@ -9299,7 +9305,7 @@ Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID, if (ReturnValue.isNull()) return MvecOut; else - return Builder.CreateStore(MvecOut, ReturnValue.getValue()); + return Builder.CreateStore(MvecOut, ReturnValue.getAddress()); } case CustomCodeGen::VST24: { @@ -11479,7 +11485,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -13345,15 +13351,15 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID, if (!getDebugInfo()) { CGM.Error(E->getExprLoc(), "using __builtin_preserve_field_info() without -g"); - return IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + return IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); } // Enable underlying preserve_*_access_index() generation. bool OldIsInPreservedAIRegion = IsInPreservedAIRegion; IsInPreservedAIRegion = true; - Value *FieldAddr = IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + Value *FieldAddr = IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); IsInPreservedAIRegion = OldIsInPreservedAIRegion; ConstantInt *C = cast(EmitScalarExpr(E->getArg(1))); @@ -14345,14 +14351,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { - Address Tmp = CreateMemTemp(E->getArg(0)->getType()); + RawAddress Tmp = CreateMemTemp(E->getArg(0)->getType()); Builder.CreateStore(Ops[0], Tmp); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), Tmp.getPointer()); } case X86::BI_mm_getcsr: case X86::BI__builtin_ia32_stmxcsr: { - Address Tmp = CreateMemTemp(E->getType()); + RawAddress Tmp = CreateMemTemp(E->getType()); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), Tmp.getPointer()); return Builder.CreateLoad(Tmp, "stmxcsr"); @@ -17627,7 +17633,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, SmallVector Ops; for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) if (E->getArg(i)->getType()->isArrayType()) - Ops.push_back(EmitArrayToPointerDecay(E->getArg(i)).getPointer()); + Ops.push_back( + EmitArrayToPointerDecay(E->getArg(i)).emitRawPointer(*this)); else Ops.push_back(EmitScalarExpr(E->getArg(i))); // The first argument of these two builtins is a pointer used to store their @@ -20089,14 +20096,14 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, // Save returned values. assert(II.NumResults); if (II.NumResults == 1) { - Builder.CreateAlignedStore(Result, Dst.getPointer(), + Builder.CreateAlignedStore(Result, Dst.emitRawPointer(*this), CharUnits::fromQuantity(4)); } else { for (unsigned i = 0; i < II.NumResults; ++i) { Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), Dst.getElementType()), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); } @@ -20136,7 +20143,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < II.NumResults; ++i) { Value *V = Builder.CreateAlignedLoad( Src.getElementType(), - Builder.CreateGEP(Src.getElementType(), Src.getPointer(), + Builder.CreateGEP(Src.getElementType(), Src.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, ParamType)); @@ -20208,7 +20215,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsA; ++i) { Value *V = Builder.CreateAlignedLoad( SrcA.getElementType(), - Builder.CreateGEP(SrcA.getElementType(), SrcA.getPointer(), + Builder.CreateGEP(SrcA.getElementType(), SrcA.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, AType)); @@ -20218,7 +20225,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsB; ++i) { Value *V = Builder.CreateAlignedLoad( SrcB.getElementType(), - Builder.CreateGEP(SrcB.getElementType(), SrcB.getPointer(), + Builder.CreateGEP(SrcB.getElementType(), SrcB.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, BType)); @@ -20229,7 +20236,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsC; ++i) { Value *V = Builder.CreateAlignedLoad( SrcC.getElementType(), - Builder.CreateGEP(SrcC.getElementType(), SrcC.getPointer(), + Builder.CreateGEP(SrcC.getElementType(), SrcC.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, CType)); @@ -20239,7 +20246,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsD; ++i) Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); return Result; @@ -20497,7 +20504,7 @@ struct BuiltinAlignArgs { BuiltinAlignArgs(const CallExpr *E, CodeGenFunction &CGF) { QualType AstType = E->getArg(0)->getType(); if (AstType->isArrayType()) - Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(CGF); else Src = CGF.EmitScalarExpr(E->getArg(0)); SrcType = Src->getType(); @@ -21115,7 +21122,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_get: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Function *Callee; if (E->getType().isWebAssemblyExternrefType()) @@ -21129,7 +21136,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_set: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Function *Callee; @@ -21144,13 +21151,13 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_size: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Value = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Value = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_table_size); return Builder.CreateCall(Callee, Value); } case WebAssembly::BI__builtin_wasm_table_grow: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Val = EmitScalarExpr(E->getArg(1)); Value *NElems = EmitScalarExpr(E->getArg(2)); @@ -21167,7 +21174,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_fill: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Value *NElems = EmitScalarExpr(E->getArg(3)); @@ -21185,8 +21192,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_copy: { assert(E->getArg(0)->getType()->isArrayType()); - Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); - Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).getPointer(); + Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).emitRawPointer(*this); Value *DstIdx = EmitScalarExpr(E->getArg(2)); Value *SrcIdx = EmitScalarExpr(E->getArg(3)); Value *NElems = EmitScalarExpr(E->getArg(4)); @@ -21265,7 +21272,7 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, auto MakeCircOp = [this, E](unsigned IntID, bool IsLoad) { // The base pointer is passed by address, so it needs to be loaded. Address A = EmitPointerWithAlignment(E->getArg(0)); - Address BP = Address(A.getPointer(), Int8PtrTy, A.getAlignment()); + Address BP = Address(A.emitRawPointer(*this), Int8PtrTy, A.getAlignment()); llvm::Value *Base = Builder.CreateLoad(BP); // The treatment of both loads and stores is the same: the arguments for // the builtin are the same as the arguments for the intrinsic. @@ -21306,8 +21313,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression // per call. Address DestAddr = EmitPointerWithAlignment(E->getArg(1)); - DestAddr = Address(DestAddr.getPointer(), Int8Ty, DestAddr.getAlignment()); - llvm::Value *DestAddress = DestAddr.getPointer(); + DestAddr = DestAddr.withElementType(Int8Ty); + llvm::Value *DestAddress = DestAddr.emitRawPointer(*this); // Operands are Base, Dest, Modifier. // The intrinsic format in LLVM IR is defined as @@ -21358,8 +21365,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), PredIn}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } // These are identical to the builtins above, except they don't consume @@ -21377,8 +21384,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index b756318c46a9..0cb5b06a519c 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -331,11 +331,11 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, llvm::ConstantInt::get(SizeTy, std::max(1, Args.size()))); // Store pointers to the arguments in a locally allocated launch_args. for (unsigned i = 0; i < Args.size(); ++i) { - llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer(); + llvm::Value *VarPtr = CGF.GetAddrOfLocalVar(Args[i]).emitRawPointer(CGF); llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, PtrTy); CGF.Builder.CreateDefaultAlignedStore( - VoidVarPtr, - CGF.Builder.CreateConstGEP1_32(PtrTy, KernelArgs.getPointer(), i)); + VoidVarPtr, CGF.Builder.CreateConstGEP1_32( + PtrTy, KernelArgs.emitRawPointer(CGF), i)); } llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); @@ -393,9 +393,10 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, /*isVarArg=*/false), addUnderscoredPrefixToName("PopCallConfiguration")); - CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, - {GridDim.getPointer(), BlockDim.getPointer(), - ShmemSize.getPointer(), Stream.getPointer()}); + CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, {GridDim.emitRawPointer(CGF), + BlockDim.emitRawPointer(CGF), + ShmemSize.emitRawPointer(CGF), + Stream.emitRawPointer(CGF)}); // Emit the call to cudaLaunch llvm::Value *Kernel = @@ -405,7 +406,7 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, cudaLaunchKernelFD->getParamDecl(0)->getType()); LaunchKernelArgs.add(RValue::getAggregate(GridDim), Dim3Ty); LaunchKernelArgs.add(RValue::getAggregate(BlockDim), Dim3Ty); - LaunchKernelArgs.add(RValue::get(KernelArgs.getPointer()), + LaunchKernelArgs.add(RValue::get(KernelArgs, CGF), cudaLaunchKernelFD->getParamDecl(3)->getType()); LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(ShmemSize)), cudaLaunchKernelFD->getParamDecl(4)->getType()); @@ -438,8 +439,8 @@ void CGNVCUDARuntime::emitDeviceStubBodyLegacy(CodeGenFunction &CGF, auto TInfo = CGM.getContext().getTypeInfoInChars(A->getType()); Offset = Offset.alignTo(TInfo.Align); llvm::Value *Args[] = { - CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(), - PtrTy), + CGF.Builder.CreatePointerCast( + CGF.GetAddrOfLocalVar(A).emitRawPointer(CGF), PtrTy), llvm::ConstantInt::get(SizeTy, TInfo.Width.getQuantity()), llvm::ConstantInt::get(SizeTy, Offset.getQuantity()), }; diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index a8bf57a277e9..7c6dfc3e59d8 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -20,6 +20,12 @@ using namespace CodeGen; CGCXXABI::~CGCXXABI() { } +Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) { + return CGF.makeNaturalAddressForPointer( + CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(), + CGF.CXXABIThisAlignment); +} + void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { DiagnosticsEngine &Diags = CGF.CGM.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -44,8 +50,12 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *MemPtr, const MemberPointerType *MPT) { ErrorUnsupportedABI(CGF, "calls through member pointers"); - ThisPtrForCall = This.getPointer(); - const auto *FPT = MPT->getPointeeType()->castAs(); + const auto *RD = + cast(MPT->getClass()->castAs()->getDecl()); + ThisPtrForCall = + CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD)); + const FunctionProtoType *FPT = + MPT->getPointeeType()->getAs(); llvm::Constant *FnPtr = llvm::Constant::getNullValue( llvm::PointerType::getUnqual(CGM.getLLVMContext())); return CGCallee::forDirect(FnPtr, FPT); @@ -251,16 +261,15 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, // If we don't need an array cookie, bail out early. if (!requiresArrayCookie(expr, eltTy)) { - allocPtr = ptr.getPointer(); + allocPtr = ptr.emitRawPointer(CGF); numElements = nullptr; cookieSize = CharUnits::Zero(); return; } cookieSize = getArrayCookieSizeImpl(eltTy); - Address allocAddr = - CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); - allocPtr = allocAddr.getPointer(); + Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); + allocPtr = allocAddr.emitRawPointer(CGF); numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); } diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index ad1ad08d0856..c7eccbd0095a 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -57,12 +57,8 @@ protected: llvm::Value *getThisValue(CodeGenFunction &CGF) { return CGF.CXXABIThisValue; } - Address getThisAddress(CodeGenFunction &CGF) { - return Address( - CGF.CXXABIThisValue, - CGF.ConvertTypeForMem(CGF.CXXABIThisDecl->getType()->getPointeeType()), - CGF.CXXABIThisAlignment); - } + + Address getThisAddress(CodeGenFunction &CGF); /// Issue a diagnostic about unsupported features in the ABI. void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S); @@ -475,12 +471,6 @@ public: BaseSubobject Base, const CXXRecordDecl *NearestVBase) = 0; - /// Get the address point of the vtable for the given base subobject while - /// building a constexpr. - virtual llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) = 0; - /// Get the address of the vtable for the given record decl which should be /// used for the vptr at the given offset in RD. virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index b8adf5c26b3a..fb0078214b07 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1037,15 +1037,9 @@ static void forConstantArrayExpansion(CodeGenFunction &CGF, ConstantArrayExpansion *CAE, Address BaseAddr, llvm::function_ref Fn) { - CharUnits EltSize = CGF.getContext().getTypeSizeInChars(CAE->EltTy); - CharUnits EltAlign = - BaseAddr.getAlignment().alignmentOfArrayElement(EltSize); - llvm::Type *EltTy = CGF.ConvertTypeForMem(CAE->EltTy); - for (int i = 0, n = CAE->NumElts; i < n; i++) { - llvm::Value *EltAddr = CGF.Builder.CreateConstGEP2_32( - BaseAddr.getElementType(), BaseAddr.getPointer(), 0, i); - Fn(Address(EltAddr, EltTy, EltAlign)); + Address EltAddr = CGF.Builder.CreateConstGEP2_32(BaseAddr, 0, i); + Fn(EltAddr); } } @@ -1160,9 +1154,10 @@ void CodeGenFunction::ExpandTypeToArgs( } /// Create a temporary allocation for the purposes of coercion. -static Address CreateTempAllocaForCoercion(CodeGenFunction &CGF, llvm::Type *Ty, - CharUnits MinAlign, - const Twine &Name = "tmp") { +static RawAddress CreateTempAllocaForCoercion(CodeGenFunction &CGF, + llvm::Type *Ty, + CharUnits MinAlign, + const Twine &Name = "tmp") { // Don't use an alignment that's worse than what LLVM would prefer. auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlign(Ty); CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign)); @@ -1332,11 +1327,11 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, } // Otherwise do coercion through memory. This is stupid, but simple. - Address Tmp = + RawAddress Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName()); CGF.Builder.CreateMemCpy( - Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), + Src.emitRawPointer(CGF), Src.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinValue())); return CGF.Builder.CreateLoad(Tmp); } @@ -1420,11 +1415,12 @@ static void CreateCoercedStore(llvm::Value *Src, // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); + RawAddress Tmp = + CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); CGF.Builder.CreateStore(Src, Tmp); CGF.Builder.CreateMemCpy( - Dst.getPointer(), Dst.getAlignment().getAsAlign(), Tmp.getPointer(), - Tmp.getAlignment().getAsAlign(), + Dst.emitRawPointer(CGF), Dst.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, DstSize.getFixedValue())); } } @@ -3024,17 +3020,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Indirect: case ABIArgInfo::IndirectAliased: { assert(NumIRArgs == 1); - Address ParamAddr = Address(Fn->getArg(FirstIRArg), ConvertTypeForMem(Ty), - ArgI.getIndirectAlign(), KnownNonNull); + Address ParamAddr = makeNaturalAddressForPointer( + Fn->getArg(FirstIRArg), Ty, ArgI.getIndirectAlign(), false, nullptr, + nullptr, KnownNonNull); if (!hasScalarEvaluationKind(Ty)) { // Aggregates and complex variables are accessed by reference. All we // need to do is realign the value, if requested. Also, if the address // may be aliased, copy it to ensure that the parameter variable is // mutable and has a unique adress, as C requires. - Address V = ParamAddr; if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) { - Address AlignedTemp = CreateMemTemp(Ty, "coerce"); + RawAddress AlignedTemp = CreateMemTemp(Ty, "coerce"); // Copy from the incoming argument pointer to the temporary with the // appropriate alignment. @@ -3044,11 +3040,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, CharUnits Size = getContext().getTypeSizeInChars(Ty); Builder.CreateMemCpy( AlignedTemp.getPointer(), AlignedTemp.getAlignment().getAsAlign(), - ParamAddr.getPointer(), ParamAddr.getAlignment().getAsAlign(), + ParamAddr.emitRawPointer(*this), + ParamAddr.getAlignment().getAsAlign(), llvm::ConstantInt::get(IntPtrTy, Size.getQuantity())); - V = AlignedTemp; + ParamAddr = AlignedTemp; } - ArgVals.push_back(ParamValue::forIndirect(V)); + ArgVals.push_back(ParamValue::forIndirect(ParamAddr)); } else { // Load scalar value from indirect argument. llvm::Value *V = @@ -3162,10 +3159,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, == ParameterABI::SwiftErrorResult) { QualType pointeeTy = Ty->getPointeeType(); assert(pointeeTy->isPointerType()); - Address temp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - Address arg(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + RawAddress temp = + CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); + Address arg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); Builder.CreateStore(incomingErrorValue, temp); V = temp.getPointer(); @@ -3502,7 +3499,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, llvm::LoadInst *load = dyn_cast(retainedValue->stripPointerCasts()); if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer()) + load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) return nullptr; // Okay! Burn it all down. This relies for correctness on the @@ -3539,12 +3536,15 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { + llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); + // Check if a User is a store which pointerOperand is the ReturnValue. // We are looking for stores to the ReturnValue, not for stores of the // ReturnValue to some other location. - auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * { + auto GetStoreIfValid = [&CGF, + ReturnValuePtr](llvm::User *U) -> llvm::StoreInst * { auto *SI = dyn_cast(U); - if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer() || + if (!SI || SI->getPointerOperand() != ReturnValuePtr || SI->getValueOperand()->getType() != CGF.ReturnValue.getElementType()) return nullptr; // These aren't actually possible for non-coerced returns, and we @@ -3558,7 +3558,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { // for something immediately preceding the IP. Sometimes this can // happen with how we generate implicit-returns; it can also happen // with noreturn cleanups. - if (!CGF.ReturnValue.getPointer()->hasOneUse()) { + if (!ReturnValuePtr->hasOneUse()) { llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); if (IP->empty()) return nullptr; @@ -3576,8 +3576,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { return nullptr; } - llvm::StoreInst *store = - GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back()); + llvm::StoreInst *store = GetStoreIfValid(ReturnValuePtr->user_back()); if (!store) return nullptr; // Now do a first-and-dirty dominance check: just walk up the @@ -4121,7 +4120,11 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, } static bool isProvablyNull(llvm::Value *addr) { - return isa(addr); + return llvm::isa_and_nonnull(addr); +} + +static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { + return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. @@ -4129,21 +4132,20 @@ static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; Address srcAddr = srcLV.getAddress(CGF); - assert(!isProvablyNull(srcAddr.getPointer()) && + assert(!isProvablyNull(srcAddr.getBasePointer()) && "shouldn't have writeback for provably null argument"); llvm::BasicBlock *contBB = nullptr; // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); CGF.Builder.CreateCondBr(isNull, contBB, writebackBB); CGF.EmitBlock(writebackBB); } @@ -4247,7 +4249,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getPointer())) { + if (isProvablyNull(srcAddr.getBasePointer())) { args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), CRE->getType()); return; @@ -4276,17 +4278,16 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (provablyNonNull) { - finalArgument = temp.getPointer(); + finalArgument = temp.emitRawPointer(CGF); } else { - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); - finalArgument = CGF.Builder.CreateSelect(isNull, - llvm::ConstantPointerNull::get(destType), - temp.getPointer(), "icr.argument"); + finalArgument = CGF.Builder.CreateSelect( + isNull, llvm::ConstantPointerNull::get(destType), + temp.emitRawPointer(CGF), "icr.argument"); // If we need to copy, then the load has to be conditional, which // means we need control flow. @@ -4410,6 +4411,16 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, std::nullopt); } +void CodeGenFunction::EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, + AbstractCallee AC, unsigned ParmNum) { + if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || + SanOpts.has(SanitizerKind::NullabilityArg))) + return; + + EmitNonNullArgCheck(RValue::get(Addr, *this), ArgType, ArgLoc, AC, ParmNum); +} + // Check if the call is going to use the inalloca convention. This needs to // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged // later, so we can't check it directly. @@ -4750,10 +4761,20 @@ CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) { llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const llvm::Twine &name) { - return EmitNounwindRuntimeCall(callee, std::nullopt, name); + return EmitNounwindRuntimeCall(callee, ArrayRef(), name); } /// Emits a call to the given nounwind runtime function. +llvm::CallInst * +CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef
args, + const llvm::Twine &name) { + SmallVector values; + for (auto arg : args) + values.push_back(arg.emitRawPointer(*this)); + return EmitNounwindRuntimeCall(callee, values, name); +} + llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, @@ -5032,7 +5053,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If we're using inalloca, insert the allocation after the stack save. // FIXME: Do this earlier rather than hacking it in here! - Address ArgMemory = Address::invalid(); + RawAddress ArgMemory = RawAddress::invalid(); if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { const llvm::DataLayout &DL = CGM.getDataLayout(); llvm::Instruction *IP = CallArgs.getStackBase(); @@ -5048,7 +5069,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI->setAlignment(Align.getAsAlign()); AI->setUsedWithInAlloca(true); assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); - ArgMemory = Address(AI, ArgStruct, Align); + ArgMemory = RawAddress(AI, ArgStruct, Align); } ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo); @@ -5057,11 +5078,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); - Address SRetAlloca = Address::invalid(); + RawAddress SRetAlloca = RawAddress::invalid(); llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getValue(); + SRetPtr = ReturnValue.getAddress(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); if (HaveInsertPoint() && ReturnValue.isUnused()) { @@ -5071,15 +5092,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } if (IRFunctionArgs.hasSRetArg()) { - IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); + IRCallArgs[IRFunctionArgs.getSRetArgNo()] = + getAsNaturalPointerTo(SRetPtr, RetTy); } else if (RetAI.isInAlloca()) { Address Addr = Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex()); - Builder.CreateStore(SRetPtr.getPointer(), Addr); + Builder.CreateStore(getAsNaturalPointerTo(SRetPtr, RetTy), Addr); } } - Address swiftErrorTemp = Address::invalid(); + RawAddress swiftErrorTemp = RawAddress::invalid(); Address swiftErrorArg = Address::invalid(); // When passing arguments using temporary allocas, we need to add the @@ -5112,9 +5134,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 0); assert(getTarget().getTriple().getArch() == llvm::Triple::x86); if (I->isAggregate()) { - Address Addr = I->hasLValue() - ? I->getKnownLValue().getAddress(*this) - : I->getKnownRValue().getAggregateAddress(); + RawAddress Addr = I->hasLValue() + ? I->getKnownLValue().getAddress(*this) + : I->getKnownRValue().getAggregateAddress(); llvm::Instruction *Placeholder = cast(Addr.getPointer()); @@ -5138,7 +5160,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else if (ArgInfo.getInAllocaIndirect()) { // Make a temporary alloca and store the address of it into the argument // struct. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, getContext().getTypeAlignInChars(I->Ty), "indirect-arg-temp"); I->copyInto(*this, Addr); @@ -5160,12 +5182,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 1); if (!I->isAggregate()) { // Make a temporary alloca to pass the argument. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "indirect-arg-temp"); - llvm::Value *Val = Addr.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(Addr, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(Addr.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; I->copyInto(*this, Addr); @@ -5181,7 +5203,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Address Addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); - llvm::Value *V = Addr.getPointer(); CharUnits Align = ArgInfo.getIndirectAlign(); const llvm::DataLayout *TD = &CGM.getDataLayout(); @@ -5192,8 +5213,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, bool NeedCopy = false; if (Addr.getAlignment() < Align && - llvm::getOrEnforceKnownAlignment(V, Align.getAsAlign(), *TD) < - Align.getAsAlign()) { + llvm::getOrEnforceKnownAlignment(Addr.emitRawPointer(*this), + Align.getAsAlign(), + *TD) < Align.getAsAlign()) { NeedCopy = true; } else if (I->hasLValue()) { auto LV = I->getKnownLValue(); @@ -5224,11 +5246,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (NeedCopy) { // Create an aligned temporary, and copy to it. - Address AI = CreateMemTempWithoutCast( + RawAddress AI = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); - llvm::Value *Val = AI.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(AI, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(AI.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; // Emit lifetime markers for the temporary alloca. @@ -5245,6 +5267,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, I->copyInto(*this, AI); } else { // Skip the extra memcpy call. + llvm::Value *V = getAsNaturalPointerTo(Addr, I->Ty); auto *T = llvm::PointerType::get( CGM.getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace()); @@ -5284,8 +5307,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); QualType pointeeTy = I->Ty->getPointeeType(); - swiftErrorArg = Address(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + swiftErrorArg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); swiftErrorTemp = CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); @@ -5422,7 +5445,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *tempSize = nullptr; Address addr = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); if (I->isAggregate()) { addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); @@ -5856,7 +5879,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return RValue::getComplex(std::make_pair(Real, Imag)); } case TEK_Aggregate: { - Address DestPtr = ReturnValue.getValue(); + Address DestPtr = ReturnValue.getAddress(); bool DestIsVolatile = ReturnValue.isVolatile(); if (!DestPtr.isValid()) { diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 1bd48a072593..6b676ac196db 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -377,6 +377,7 @@ public: Address getValue() const { return Addr; } bool isUnused() const { return IsUnused; } bool isExternallyDestructed() const { return IsExternallyDestructed; } + Address getAddress() const { return Addr; } }; /// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 34319381901a..8c1c8ee455d2 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -139,8 +139,9 @@ Address CodeGenFunction::LoadCXXThisAddress() { CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent()); } - llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType()); - return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull); + return makeNaturalAddressForPointer( + LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment, + false, nullptr, nullptr, KnownNonNull); } /// Emit the address of a field using a member data pointer. @@ -270,7 +271,7 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, } // Apply the base offset. - llvm::Value *ptr = addr.getPointer(); + llvm::Value *ptr = addr.emitRawPointer(CGF); ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr"); // If we have a virtual component, the alignment of the result will @@ -338,8 +339,8 @@ Address CodeGenFunction::GetAddressOfBaseClass( if (sanitizePerformTypeCheck()) { SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, !NullCheckValue); - EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(), - DerivedTy, DerivedAlign, SkippedChecks); + EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy, + DerivedAlign, SkippedChecks); } return Value.withElementType(BaseValueTy); } @@ -354,7 +355,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull"); endBB = createBasicBlock("cast.end"); - llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer()); + llvm::Value *isNull = Builder.CreateIsNull(Value); Builder.CreateCondBr(isNull, endBB, notNullBB); EmitBlock(notNullBB); } @@ -363,14 +364,15 @@ Address CodeGenFunction::GetAddressOfBaseClass( SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, - Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks); + Value.emitRawPointer(*this), DerivedTy, DerivedAlign, + SkippedChecks); } // Compute the virtual offset. llvm::Value *VirtualOffset = nullptr; if (VBase) { VirtualOffset = - CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); + CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); } // Apply both offsets. @@ -387,7 +389,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( EmitBlock(endBB); llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result"); - PHI->addIncoming(Value.getPointer(), notNullBB); + PHI->addIncoming(Value.emitRawPointer(*this), notNullBB); PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB); Value = Value.withPointer(PHI, NotKnownNonNull); } @@ -424,15 +426,19 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, CastNotNull = createBasicBlock("cast.notnull"); CastEnd = createBasicBlock("cast.end"); - llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } // Apply the offset. - llvm::Value *Value = BaseAddr.getPointer(); - Value = Builder.CreateInBoundsGEP( - Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr"); + Address Addr = BaseAddr.withElementType(Int8Ty); + Addr = Builder.CreateInBoundsGEP( + Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty, + CGM.getClassPointerAlignment(Derived), "sub.ptr"); + + // Just cast. + Addr = Addr.withElementType(DerivedValueTy); // Produce a PHI if we had a null-check. if (NullCheckValue) { @@ -441,13 +447,15 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, Builder.CreateBr(CastEnd); EmitBlock(CastEnd); + llvm::Value *Value = Addr.emitRawPointer(*this); llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); PHI->addIncoming(Value, CastNotNull); PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); - Value = PHI; + return Address(PHI, Addr.getElementType(), + CGM.getClassPointerAlignment(Derived)); } - return Address(Value, DerivedValueTy, CGM.getClassPointerAlignment(Derived)); + return Addr; } llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, @@ -1719,7 +1727,7 @@ namespace { // Use the base class declaration location as inline DebugLocation. All // fields of the class are destroyed. DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass); - EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(), + EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF), BaseSize.getQuantity()); // Prevent the current stack frame from disappearing from the stack trace. @@ -2022,7 +2030,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, // Find the end of the array. llvm::Type *elementType = arrayBase.getElementType(); - llvm::Value *arrayBegin = arrayBase.getPointer(); + llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this); llvm::Value *arrayEnd = Builder.CreateInBoundsGEP( elementType, arrayBegin, numElements, "arrayctor.end"); @@ -2118,14 +2126,15 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, Address This = ThisAVS.getAddress(); LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace(); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = + getAsNaturalPointerTo(This, D->getThisType()->getPointeeType()); if (SlotAS != ThisAS) { unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); llvm::Type *NewType = llvm::PointerType::get(getLLVMContext(), TargetThisAS); - ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), - ThisAS, SlotAS, NewType); + ThisPtr = getTargetHooks().performAddrSpaceCast(*this, ThisPtr, ThisAS, + SlotAS, NewType); } // Push the this ptr. @@ -2194,7 +2203,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const CXXRecordDecl *ClassDecl = D->getParent(); if (!NewPointerIsChecked) - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This, getContext().getRecordType(ClassDecl), CharUnits::Zero()); if (D->isTrivial() && D->isDefaultConstructor()) { @@ -2207,10 +2216,9 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // model that copy. if (isMemcpyEquivalentSpecialMember(D)) { assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); - QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); - Address Src = Address(Args[1].getRValue(*this).getScalarVal(), ConvertTypeForMem(SrcTy), - CGM.getNaturalTypeAlignment(SrcTy)); + Address Src = makeNaturalAddressForPointer( + Args[1].getRValue(*this).getScalarVal(), SrcTy); LValue SrcLVal = MakeAddrLValue(Src, SrcTy); QualType DestTy = getContext().getTypeDeclType(ClassDecl); LValue DestLVal = MakeAddrLValue(This, DestTy); @@ -2263,7 +2271,9 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall( const CXXConstructorDecl *D, bool ForVirtualBase, Address This, bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) { CallArgList Args; - CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType()); + CallArg ThisArg(RValue::get(getAsNaturalPointerTo( + This, D->getThisType()->getPointeeType())), + D->getThisType()); // Forward the parameters. if (InheritedFromVBase && @@ -2388,12 +2398,14 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, CallArgList Args; // Push the this ptr. - Args.add(RValue::get(This.getPointer()), D->getThisType()); + Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())), + D->getThisType()); // Push the src ptr. QualType QT = *(FPT->param_type_begin()); llvm::Type *t = CGM.getTypes().ConvertType(QT); - llvm::Value *SrcVal = Builder.CreateBitCast(Src.getPointer(), t); + llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType()); + llvm::Value *SrcVal = Builder.CreateBitCast(Val, t); Args.add(RValue::get(SrcVal), QT); // Skip over first argument (Src). @@ -2418,7 +2430,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // this Address This = LoadCXXThisAddress(); - DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); + DelegateArgs.add(RValue::get(getAsNaturalPointerTo( + This, (*I)->getType()->getPointeeType())), + (*I)->getType()); ++I; // FIXME: The location of the VTT parameter in the parameter list is @@ -2775,7 +2789,7 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived, if (MayBeNull) { llvm::Value *DerivedNotNull = - Builder.CreateIsNotNull(Derived.getPointer(), "cast.nonnull"); + Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull"); llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check"); ContBlock = createBasicBlock("cast.cont"); @@ -2976,7 +2990,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); Address ThisPtr = GetAddrOfBlockDecl(variable); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType); // Add the rest of the parameters. for (auto *param : BD->parameters()) @@ -3004,7 +3018,7 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { QualType LambdaType = getContext().getRecordType(Lambda); QualType ThisType = getContext().getPointerType(LambdaType); Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType); EmitLambdaDelegatingInvokeBody(MD, CallArgs); } diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index f87caf050eea..e6f8e6873004 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -27,7 +27,7 @@ bool DominatingValue::saved_type::needsSaving(RValue rv) { if (rv.isScalar()) return DominatingLLVMValue::needsSaving(rv.getScalarVal()); if (rv.isAggregate()) - return DominatingLLVMValue::needsSaving(rv.getAggregatePointer()); + return DominatingValue
::needsSaving(rv.getAggregateAddress()); return true; } @@ -35,69 +35,40 @@ DominatingValue::saved_type DominatingValue::saved_type::save(CodeGenFunction &CGF, RValue rv) { if (rv.isScalar()) { llvm::Value *V = rv.getScalarVal(); - - // These automatically dominate and don't need to be saved. - if (!DominatingLLVMValue::needsSaving(V)) - return saved_type(V, nullptr, ScalarLiteral); - - // Everything else needs an alloca. - Address addr = - CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue"); - CGF.Builder.CreateStore(V, addr); - return saved_type(addr.getPointer(), nullptr, ScalarAddress); + return saved_type(DominatingLLVMValue::save(CGF, V), + DominatingLLVMValue::needsSaving(V) ? ScalarAddress + : ScalarLiteral); } if (rv.isComplex()) { CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); - llvm::Type *ComplexTy = - llvm::StructType::get(V.first->getType(), V.second->getType()); - Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex"); - CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0)); - CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1)); - return saved_type(addr.getPointer(), nullptr, ComplexAddress); + return saved_type(DominatingLLVMValue::save(CGF, V.first), + DominatingLLVMValue::save(CGF, V.second)); } assert(rv.isAggregate()); - Address V = rv.getAggregateAddress(); // TODO: volatile? - if (!DominatingLLVMValue::needsSaving(V.getPointer())) - return saved_type(V.getPointer(), V.getElementType(), AggregateLiteral, - V.getAlignment().getQuantity()); - - Address addr = - CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue"); - CGF.Builder.CreateStore(V.getPointer(), addr); - return saved_type(addr.getPointer(), V.getElementType(), AggregateAddress, - V.getAlignment().getQuantity()); + Address V = rv.getAggregateAddress(); + return saved_type( + DominatingValue
::save(CGF, V), rv.isVolatileQualified(), + DominatingValue
::needsSaving(V) ? AggregateAddress + : AggregateLiteral); } /// Given a saved r-value produced by SaveRValue, perform the code /// necessary to restore it to usability at the current insertion /// point. RValue DominatingValue::saved_type::restore(CodeGenFunction &CGF) { - auto getSavingAddress = [&](llvm::Value *value) { - auto *AI = cast(value); - return Address(value, AI->getAllocatedType(), - CharUnits::fromQuantity(AI->getAlign().value())); - }; switch (K) { case ScalarLiteral: - return RValue::get(Value); case ScalarAddress: - return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value))); + return RValue::get(DominatingLLVMValue::restore(CGF, Vals.first)); case AggregateLiteral: + case AggregateAddress: return RValue::getAggregate( - Address(Value, ElementType, CharUnits::fromQuantity(Align))); - case AggregateAddress: { - auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value)); - return RValue::getAggregate( - Address(addr, ElementType, CharUnits::fromQuantity(Align))); - } + DominatingValue
::restore(CGF, AggregateAddr), IsVolatile); case ComplexAddress: { - Address address = getSavingAddress(Value); - llvm::Value *real = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 0)); - llvm::Value *imag = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 1)); + llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first); + llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second); return RValue::getComplex(real, imag); } } @@ -294,14 +265,14 @@ void EHScopeStack::popNullFixups() { BranchFixups.pop_back(); } -Address CodeGenFunction::createCleanupActiveFlag() { +RawAddress CodeGenFunction::createCleanupActiveFlag() { // Create a variable to decide whether the cleanup needs to be run. - Address active = CreateTempAllocaWithoutCast( + RawAddress active = CreateTempAllocaWithoutCast( Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); // Initialize it to false at a site that's guaranteed to be run // before each evaluation. - setBeforeOutermostConditional(Builder.getFalse(), active); + setBeforeOutermostConditional(Builder.getFalse(), active, *this); // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); @@ -309,7 +280,7 @@ Address CodeGenFunction::createCleanupActiveFlag() { return active; } -void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { +void CodeGenFunction::initFullExprCleanupWithFlag(RawAddress ActiveFlag) { // Set that as the active flag in the cleanup. EHCleanupScope &cleanup = cast(*EHStack.begin()); assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); @@ -322,15 +293,17 @@ void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { void EHScopeStack::Cleanup::anchor() {} static void createStoreInstBefore(llvm::Value *value, Address addr, - llvm::Instruction *beforeInst) { - auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + auto store = new llvm::StoreInst(value, addr.emitRawPointer(CGF), beforeInst); store->setAlignment(addr.getAlignment().getAsAlign()); } static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, - llvm::Instruction *beforeInst) { - return new llvm::LoadInst(addr.getElementType(), addr.getPointer(), name, - false, addr.getAlignment().getAsAlign(), + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + return new llvm::LoadInst(addr.getElementType(), addr.emitRawPointer(CGF), + name, false, addr.getAlignment().getAsAlign(), beforeInst); } @@ -357,8 +330,8 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF, // entry which we're currently popping. if (Fixup.OptimisticBranchBlock == nullptr) { createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex), - CGF.getNormalCleanupDestSlot(), - Fixup.InitialBranch); + CGF.getNormalCleanupDestSlot(), Fixup.InitialBranch, + CGF); Fixup.InitialBranch->setSuccessor(0, CleanupEntry); } @@ -385,7 +358,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, if (llvm::BranchInst *Br = dyn_cast(Term)) { assert(Br->isUnconditional()); auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(), - "cleanup.dest", Term); + "cleanup.dest", Term, CGF); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); Br->eraseFromParent(); @@ -513,8 +486,8 @@ void CodeGenFunction::PopCleanupBlocks( I += Header.getSize(); if (Header.isConditional()) { - Address ActiveFlag = - reinterpret_cast
(LifetimeExtendedCleanupStack[I]); + RawAddress ActiveFlag = + reinterpret_cast(LifetimeExtendedCleanupStack[I]); initFullExprCleanupWithFlag(ActiveFlag); I += sizeof(ActiveFlag); } @@ -888,7 +861,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (NormalCleanupDestSlot->hasOneUse()) { NormalCleanupDestSlot->user_back()->eraseFromParent(); NormalCleanupDestSlot->eraseFromParent(); - NormalCleanupDest = Address::invalid(); + NormalCleanupDest = RawAddress::invalid(); } llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); @@ -912,9 +885,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // pass the abnormal exit flag to Fn (SEH cleanup) cleanupFlags.setHasExitSwitch(); - llvm::LoadInst *Load = - createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest", - nullptr); + llvm::LoadInst *Load = createLoadInstBefore( + getNormalCleanupDestSlot(), "cleanup.dest", nullptr, *this); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Default, SwitchCapacity); @@ -961,8 +933,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (!Fixup.Destination) continue; if (!Fixup.OptimisticBranchBlock) { createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex), - getNormalCleanupDestSlot(), - Fixup.InitialBranch); + getNormalCleanupDestSlot(), Fixup.InitialBranch, + *this); Fixup.InitialBranch->setSuccessor(0, NormalEntry); } Fixup.OptimisticBranchBlock = NormalExit; @@ -1135,7 +1107,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { // Store the index at the start. llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); - createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI); + createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI, *this); // Adjust BI to point to the first cleanup block. { @@ -1269,9 +1241,9 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF, // If we're in a conditional block, ignore the dominating IP and // use the outermost conditional branch. if (CGF.isInConditionalBranch()) { - CGF.setBeforeOutermostConditional(value, var); + CGF.setBeforeOutermostConditional(value, var, CGF); } else { - createStoreInstBefore(value, var, dominatingIP); + createStoreInstBefore(value, var, dominatingIP, CGF); } } @@ -1321,7 +1293,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, Scope.setActive(false); } -Address CodeGenFunction::getNormalCleanupDestSlot() { +RawAddress CodeGenFunction::getNormalCleanupDestSlot() { if (!NormalCleanupDest.isValid()) NormalCleanupDest = CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h index 7a7344c07160..03e4a29d7b3d 100644 --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -333,7 +333,7 @@ public: Address getActiveFlag() const { return ActiveFlag; } - void setActiveFlag(Address Var) { + void setActiveFlag(RawAddress Var) { assert(Var.getAlignment().isOne()); ActiveFlag = Var; } diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index b7142ec08af9..93ca711f716f 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -867,8 +867,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { EmitStmt(S.getPromiseDeclStmt()); Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl()); - auto *PromiseAddrVoidPtr = - new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId); + auto *PromiseAddrVoidPtr = new llvm::BitCastInst( + PromiseAddr.emitRawPointer(*this), VoidPtrTy, "", CoroId); // Update CoroId to refer to the promise. We could not do it earlier because // promise local variable was not emitted yet. CoroId->setArgOperand(1, PromiseAddrVoidPtr); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 2ef5ed04af30..267f2e40a7bb 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1461,7 +1461,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { bool EmitDebugInfo = DI && CGM.getCodeGenOpts().hasReducedDebugInfo(); Address address = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); Address OpenMPLocalAddr = Address::invalid(); if (CGM.getLangOpts().OpenMPIRBuilder) OpenMPLocalAddr = OMPBuilderCBHelpers::getAddressOfLocalVariable(*this, &D); @@ -1524,7 +1524,10 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // return slot, so that we can elide the copy when returning this // variable (C++0x [class.copy]p34). address = ReturnValue; - AllocaAddr = ReturnValue; + AllocaAddr = + RawAddress(ReturnValue.emitRawPointer(*this), + ReturnValue.getElementType(), ReturnValue.getAlignment()); + ; if (const RecordType *RecordTy = Ty->getAs()) { const auto *RD = RecordTy->getDecl(); @@ -1535,7 +1538,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // to this variable. Set it to zero to indicate that NRVO was not // applied. llvm::Value *Zero = Builder.getFalse(); - Address NRVOFlag = + RawAddress NRVOFlag = CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo"); EnsureInsertPoint(); Builder.CreateStore(Zero, NRVOFlag); @@ -1678,7 +1681,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { } if (D.hasAttr() && HaveInsertPoint()) - EmitVarAnnotations(&D, address.getPointer()); + EmitVarAnnotations(&D, address.emitRawPointer(*this)); // Make sure we call @llvm.lifetime.end. if (emission.useLifetimeMarkers()) @@ -1851,12 +1854,13 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, llvm::Value *BaseSizeInChars = llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); Address Begin = Loc.withElementType(Int8Ty); - llvm::Value *End = Builder.CreateInBoundsGEP( - Begin.getElementType(), Begin.getPointer(), SizeVal, "vla.end"); + llvm::Value *End = Builder.CreateInBoundsGEP(Begin.getElementType(), + Begin.emitRawPointer(*this), + SizeVal, "vla.end"); llvm::BasicBlock *OriginBB = Builder.GetInsertBlock(); EmitBlock(LoopBB); llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur"); - Cur->addIncoming(Begin.getPointer(), OriginBB); + Cur->addIncoming(Begin.emitRawPointer(*this), OriginBB); CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); auto *I = Builder.CreateMemCpy(Address(Cur, Int8Ty, CurAlign), @@ -2283,7 +2287,7 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, checkZeroLength = false; } - llvm::Value *begin = addr.getPointer(); + llvm::Value *begin = addr.emitRawPointer(*this); llvm::Value *end = Builder.CreateInBoundsGEP(addr.getElementType(), begin, length); emitArrayDestroy(begin, end, type, elementAlign, destroyer, @@ -2543,7 +2547,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } Address DeclPtr = Address::invalid(); - Address AllocaPtr = Address::invalid(); + RawAddress AllocaPtr = Address::invalid(); bool DoStore = false; bool IsScalar = hasScalarEvaluationKind(Ty); bool UseIndirectDebugAddress = false; @@ -2555,8 +2559,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // Indirect argument is in alloca address space, which may be different // from the default address space. auto AllocaAS = CGM.getASTAllocaAddressSpace(); - auto *V = DeclPtr.getPointer(); - AllocaPtr = DeclPtr; + auto *V = DeclPtr.emitRawPointer(*this); + AllocaPtr = RawAddress(V, DeclPtr.getElementType(), DeclPtr.getAlignment()); // For truly ABI indirect arguments -- those that are not `byval` -- store // the address of the argument on the stack to preserve debug information. @@ -2695,7 +2699,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } if (D.hasAttr()) - EmitVarAnnotations(&D, DeclPtr.getPointer()); + EmitVarAnnotations(&D, DeclPtr.emitRawPointer(*this)); // We can only check return value nullability if all arguments to the // function satisfy their nullability preconditions. This makes it necessary diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 5a9d06da12de..34f289334a7d 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -397,7 +397,7 @@ namespace { void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { // Make sure the exception object is cleaned up if there's an // exception during initialization. - pushFullExprCleanup(EHCleanup, addr.getPointer()); + pushFullExprCleanup(EHCleanup, addr.emitRawPointer(*this)); EHScopeStack::stable_iterator cleanup = EHStack.stable_begin(); // __cxa_allocate_exception returns a void*; we need to cast this @@ -416,8 +416,8 @@ void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { /*IsInit*/ true); // Deactivate the cleanup block. - DeactivateCleanupBlock(cleanup, - cast(typedAddr.getPointer())); + DeactivateCleanupBlock( + cleanup, cast(typedAddr.emitRawPointer(*this))); } Address CodeGenFunction::getExceptionSlot() { @@ -1834,7 +1834,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, llvm::Value *ParentFP) { llvm::CallInst *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast(ParentVar.getPointer())) { + if (auto *ParentAlloca = + dyn_cast_or_null(ParentVar.getBasePointer())) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( @@ -1851,8 +1852,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, // If the parent didn't have an alloca, we're doing some nested outlining. // Just clone the existing localrecover call, but tweak the FP argument to // use our FP value. All other arguments are constants. - auto *ParentRecover = - cast(ParentVar.getPointer()->stripPointerCasts()); + auto *ParentRecover = cast( + ParentVar.emitRawPointer(*this)->stripPointerCasts()); assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && "expected alloca or localrecover in parent LocalDeclMap"); RecoverCall = cast(ParentRecover->clone()); @@ -1925,7 +1926,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, if (isa(D) && D->getType() == getContext().VoidPtrTy) { assert(D->getName().starts_with("frame_pointer")); - FramePtrAddrAlloca = cast(I.second.getPointer()); + FramePtrAddrAlloca = + cast(I.second.getBasePointer()); break; } } @@ -1986,7 +1988,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + CXXThisValue = + ThisFieldLValue.getAddress(*this).emitRawPointer(*this); } else { CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) .getScalarVal(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6491835cf8ef..36872c0fedb7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -65,21 +65,21 @@ static llvm::cl::opt ClSanitizeDebugDeoptimization( /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. -Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, - CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize) { +RawAddress +CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize) { auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); Alloca->setAlignment(Align.getAsAlign()); - return Address(Alloca, Ty, Align, KnownNonNull); + return RawAddress(Alloca, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. The alloca is casted to default address space if necessary. -Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize, - Address *AllocaAddr) { +RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize, + RawAddress *AllocaAddr) { auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); if (AllocaAddr) *AllocaAddr = Alloca; @@ -101,7 +101,7 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, Ty->getPointerTo(DestAddrSpace), /*non-null*/ true); } - return Address(V, Ty, Align, KnownNonNull); + return RawAddress(V, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates an alloca and inserts it into the entry @@ -120,28 +120,29 @@ llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, /// default alignment of the corresponding LLVM type, which is *not* /// guaranteed to be related in any way to the expected alignment of /// an AST type that might have been lowered to Ty. -Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name) { CharUnits Align = CharUnits::fromQuantity(CGM.getDataLayout().getPrefTypeAlign(Ty)); return CreateTempAlloca(Ty, Align, Name); } -Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { +RawAddress CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { CharUnits Align = getContext().getTypeAlignInChars(Ty); return CreateTempAlloca(ConvertType(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, - Address *Alloca) { +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, + RawAddress *Alloca) { // FIXME: Should we prefer the preferred type alignment here? return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, - const Twine &Name, Address *Alloca) { - Address Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, - /*ArraySize=*/nullptr, Alloca); +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, + const Twine &Name, + RawAddress *Alloca) { + RawAddress Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, + /*ArraySize=*/nullptr, Alloca); if (Ty->isConstantMatrixType()) { auto *ArrayTy = cast(Result.getElementType()); @@ -154,13 +155,14 @@ Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, return Result; } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + CharUnits Align, + const Twine &Name) { return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + const Twine &Name) { return CreateMemTempWithoutCast(Ty, getContext().getTypeAlignInChars(Ty), Name); } @@ -359,7 +361,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } else { CleanupFn = CGF.CGM.getAddrAndTypeOfCXXStructor( GlobalDecl(ReferenceTemporaryDtor, Dtor_Complete)); - CleanupArg = cast(ReferenceTemporary.getPointer()); + CleanupArg = cast(ReferenceTemporary.emitRawPointer(CGF)); } CGF.CGM.getCXXABI().registerGlobalDtor( CGF, *cast(M->getExtendingDecl()), CleanupFn, CleanupArg); @@ -384,10 +386,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } } -static Address createReferenceTemporary(CodeGenFunction &CGF, - const MaterializeTemporaryExpr *M, - const Expr *Inner, - Address *Alloca = nullptr) { +static RawAddress createReferenceTemporary(CodeGenFunction &CGF, + const MaterializeTemporaryExpr *M, + const Expr *Inner, + RawAddress *Alloca = nullptr) { auto &TCG = CGF.getTargetHooks(); switch (M->getStorageDuration()) { case SD_FullExpression: @@ -416,7 +418,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, GV->getValueType()->getPointerTo( CGF.getContext().getTargetAddressSpace(LangAS::Default))); // FIXME: Should we put the new global into a COMDAT? - return Address(C, GV->getValueType(), alignment); + return RawAddress(C, GV->getValueType(), alignment); } return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca); } @@ -448,7 +450,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { auto ownership = M->getType().getObjCLifetime(); if (ownership != Qualifiers::OCL_None && ownership != Qualifiers::OCL_ExplicitNone) { - Address Object = createReferenceTemporary(*this, M, E); + RawAddress Object = createReferenceTemporary(*this, M, E); if (auto *Var = dyn_cast(Object.getPointer())) { llvm::Type *Ty = ConvertTypeForMem(E->getType()); Object = Object.withElementType(Ty); @@ -502,8 +504,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { } // Create and initialize the reference temporary. - Address Alloca = Address::invalid(); - Address Object = createReferenceTemporary(*this, M, E, &Alloca); + RawAddress Alloca = Address::invalid(); + RawAddress Object = createReferenceTemporary(*this, M, E, &Alloca); if (auto *Var = dyn_cast( Object.getPointer()->stripPointerCasts())) { llvm::Type *TemporaryType = ConvertTypeForMem(E->getType()); @@ -1111,12 +1113,12 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( } else if (const MemberExpr *ME = dyn_cast(StructBase)) { LValue LV = EmitMemberExpr(ME); Address Addr = LV.getAddress(*this); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else if (StructBase->getType()->isPointerType()) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else { return nullptr; } @@ -1282,8 +1284,7 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { if (BaseInfo) BaseInfo->mergeForCast(TargetTypeBaseInfo); - Addr = Address(Addr.getPointer(), Addr.getElementType(), Align, - IsKnownNonNull); + Addr.setAlignment(Align); } } @@ -1300,8 +1301,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, CGF.ConvertTypeForMem(E->getType()->getPointeeType()); Addr = Addr.withElementType(ElemTy); if (CE->getCastKind() == CK_AddressSpaceConversion) - Addr = CGF.Builder.CreateAddrSpaceCast(Addr, - CGF.ConvertType(E->getType())); + Addr = CGF.Builder.CreateAddrSpaceCast( + Addr, CGF.ConvertType(E->getType()), ElemTy); return Addr; } break; @@ -1364,10 +1365,9 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. - CharUnits Align = - CGF.CGM.getNaturalPointeeTypeAlignment(E->getType(), BaseInfo, TBAAInfo); - llvm::Type *ElemTy = CGF.ConvertTypeForMem(E->getType()->getPointeeType()); - return Address(CGF.EmitScalarExpr(E), ElemTy, Align, IsKnownNonNull); + return CGF.makeNaturalAddressForPointer( + CGF.EmitScalarExpr(E), E->getType()->getPointeeType(), CharUnits(), + /*ForPointeeType=*/true, BaseInfo, TBAAInfo, IsKnownNonNull); } /// EmitPointerWithAlignment - Given an expression of pointer type, try to @@ -1468,8 +1468,7 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) { if (IsBaseCXXThis || isa(ME->getBase())) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(*this), E->getType(), - LV.getAlignment(), SkippedChecks); + EmitTypeCheck(TCK, E->getExprLoc(), LV, E->getType(), SkippedChecks); } return LV; } @@ -1581,11 +1580,11 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, // Defend against branches out of gnu statement expressions surrounded by // cleanups. Address Addr = LV.getAddress(*this); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.getBasePointer(); Scope.ForceCleanup({&V}); - return LValue::MakeAddr(Addr.withPointer(V, Addr.isKnownNonNull()), - LV.getType(), getContext(), LV.getBaseInfo(), - LV.getTBAAInfo()); + Addr.replaceBasePointer(V); + return LValue::MakeAddr(Addr, LV.getType(), getContext(), + LV.getBaseInfo(), LV.getTBAAInfo()); } // FIXME: Is it possible to create an ExprWithCleanups that produces a // bitfield lvalue or some other non-simple lvalue? @@ -1929,7 +1928,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getPointer())) + if (auto *GV = dyn_cast(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2039,8 +2038,9 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) { // Convert the pointer of \p Addr to a pointer to a vector (the value type of // MatrixType), if it points to a array (the memory type of MatrixType). -static Address MaybeConvertMatrixAddress(Address Addr, CodeGenFunction &CGF, - bool IsVector = true) { +static RawAddress MaybeConvertMatrixAddress(RawAddress Addr, + CodeGenFunction &CGF, + bool IsVector = true) { auto *ArrayTy = dyn_cast(Addr.getElementType()); if (ArrayTy && IsVector) { auto *VectorTy = llvm::FixedVectorType::get(ArrayTy->getElementType(), @@ -2077,7 +2077,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isInit, bool isNontemporal) { - if (auto *GV = dyn_cast(Addr.getPointer())) + if (auto *GV = dyn_cast(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2432,14 +2432,12 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); llvm::Type *ResultType = IntPtrTy; Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); - llvm::Value *RHS = dst.getPointer(); + llvm::Value *RHS = dst.emitRawPointer(*this); RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - llvm::Value *LHS = - Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, - "sub.ptr.lhs.cast"); + llvm::Value *LHS = Builder.CreatePtrToInt(LvalueDst.emitRawPointer(*this), + ResultType, "sub.ptr.lhs.cast"); llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, - BytesBetween); + CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, BytesBetween); } else if (Dst.isGlobalObjCRef()) { CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, Dst.isThreadLocalRef()); @@ -2770,12 +2768,9 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(*this), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - - QualType PointeeType = RefLVal.getType()->getPointeeType(); - CharUnits Align = CGM.getNaturalTypeAlignment( - PointeeType, PointeeBaseInfo, PointeeTBAAInfo, - /* forPointeeType= */ true); - return Address(Load, ConvertTypeForMem(PointeeType), Align); + return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + PointeeBaseInfo, PointeeTBAAInfo); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { @@ -2792,10 +2787,9 @@ Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, LValueBaseInfo *BaseInfo, TBAAAccessInfo *TBAAInfo) { llvm::Value *Addr = Builder.CreateLoad(Ptr); - return Address(Addr, ConvertTypeForMem(PtrTy->getPointeeType()), - CGM.getNaturalTypeAlignment(PtrTy->getPointeeType(), BaseInfo, - TBAAInfo, - /*forPointeeType=*/true)); + return makeNaturalAddressForPointer(Addr, PtrTy->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + BaseInfo, TBAAInfo); } LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, @@ -2991,7 +2985,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { /* BaseInfo= */ nullptr, /* TBAAInfo= */ nullptr, /* forPointeeType= */ true); - Addr = Address(Val, ConvertTypeForMem(E->getType()), Alignment); + Addr = makeNaturalAddressForPointer(Val, T, Alignment); } return MakeAddrLValue(Addr, T, AlignmentSource::Decl); } @@ -3023,11 +3017,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), CapturedStmtInfo->getContextValue()); Address LValueAddress = CapLVal.getAddress(*this); - CapLVal = MakeAddrLValue( - Address(LValueAddress.getPointer(), LValueAddress.getElementType(), - getContext().getDeclAlign(VD)), - CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl), - CapLVal.getTBAAInfo()); + CapLVal = MakeAddrLValue(Address(LValueAddress.emitRawPointer(*this), + LValueAddress.getElementType(), + getContext().getDeclAlign(VD)), + CapLVal.getType(), + LValueBaseInfo(AlignmentSource::Decl), + CapLVal.getTBAAInfo()); // Mark lvalue as nontemporal if the variable is marked as nontemporal // in simd context. if (getLangOpts().OpenMP && @@ -3083,7 +3078,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // Handle threadlocal function locals. if (VD->getTLSKind() != VarDecl::TLS_None) addr = addr.withPointer( - Builder.CreateThreadLocalAddress(addr.getPointer()), NotKnownNonNull); + Builder.CreateThreadLocalAddress(addr.getBasePointer()), + NotKnownNonNull); // Check for OpenMP threadprivate variables. if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && @@ -3351,7 +3347,7 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) { // Pointers are passed directly, everything else is passed by address. if (!V->getType()->isPointerTy()) { - Address Ptr = CreateDefaultAlignTempAlloca(V->getType()); + RawAddress Ptr = CreateDefaultAlignTempAlloca(V->getType()); Builder.CreateStore(V, Ptr); V = Ptr.getPointer(); } @@ -3924,6 +3920,21 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, } } +static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, + ArrayRef indices, + llvm::Type *elementType, bool inbounds, + bool signedIndices, SourceLocation loc, + CharUnits align, + const llvm::Twine &name = "arrayidx") { + if (inbounds) { + return CGF.EmitCheckedInBoundsGEP(addr, indices, elementType, signedIndices, + CodeGenFunction::NotSubtraction, loc, + align, name); + } else { + return CGF.Builder.CreateGEP(addr, indices, elementType, align, name); + } +} + static CharUnits getArrayElementAlign(CharUnits arrayAlign, llvm::Value *idx, CharUnits eltSize) { @@ -3971,7 +3982,7 @@ static Address wrapWithBPFPreserveStaticOffset(CodeGenFunction &CGF, llvm::Function *Fn = CGF.CGM.getIntrinsic(llvm::Intrinsic::preserve_static_offset); - llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.getPointer()}); + llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.emitRawPointer(CGF)}); return Address(Call, Addr.getElementType(), Addr.getAlignment()); } @@ -4034,7 +4045,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, // We can use that to compute the best alignment of the element. CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType); CharUnits eltAlign = - getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); + getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); if (hasBPFPreserveStaticOffset(Base)) addr = wrapWithBPFPreserveStaticOffset(CGF, addr); @@ -4043,19 +4054,19 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, auto LastIndex = dyn_cast(indices.back()); if (!LastIndex || (!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) { - eltPtr = emitArraySubscriptGEP( - CGF, addr.getElementType(), addr.getPointer(), indices, inbounds, - signedIndices, loc, name); + addr = emitArraySubscriptGEP(CGF, addr, indices, + CGF.ConvertTypeForMem(eltType), inbounds, + signedIndices, loc, eltAlign, name); + return addr; } else { // Remember the original array subscript for bpf target unsigned idx = LastIndex->getZExtValue(); llvm::DIType *DbgInfo = nullptr; if (arrayType) DbgInfo = CGF.getDebugInfo()->getOrCreateStandaloneType(*arrayType, loc); - eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getElementType(), - addr.getPointer(), - indices.size() - 1, - idx, DbgInfo); + eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex( + addr.getElementType(), addr.emitRawPointer(CGF), indices.size() - 1, + idx, DbgInfo); } return Address(eltPtr, CGF.ConvertTypeForMem(eltType), eltAlign); @@ -4224,8 +4235,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, CharUnits EltAlign = getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); llvm::Value *EltPtr = - emitArraySubscriptGEP(*this, Int8Ty, Addr.getPointer(), ScaledIdx, - false, SignedIndices, E->getExprLoc()); + emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this), + ScaledIdx, false, SignedIndices, E->getExprLoc()); Addr = Address(EltPtr, OrigBaseElemTy, EltAlign); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the @@ -4271,7 +4282,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, llvm::Type *CountTy = ConvertType(CountFD->getType()); llvm::Value *Res = Builder.CreateInBoundsGEP( - Int8Ty, Addr.getPointer(), + Int8Ty, Addr.emitRawPointer(*this), Builder.getInt32(OffsetDiff.getQuantity()), ".counted_by.gep"); Res = Builder.CreateAlignedLoad(CountTy, Res, getIntAlign(), ".counted_by.load"); @@ -4517,9 +4528,9 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, BaseInfo = ArrayLV.getBaseInfo(); TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); } else { - Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, - TBAAInfo, BaseTy, ResultExprTy, - IsLowerBound); + Address Base = + emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy, + ResultExprTy, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*signedIndices=*/false, E->getExprLoc()); @@ -4606,7 +4617,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { SkippedChecks.set(SanitizerKind::Alignment, true); if (IsBaseCXXThis || isa(BaseExpr)) SkippedChecks.set(SanitizerKind::Null, true); - EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, + EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr, PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); } else @@ -4655,8 +4666,8 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, LambdaLV = EmitLoadOfReferenceLValue(AddrOfExplicitObject, D->getType(), AlignmentSource::Decl); else - LambdaLV = MakeNaturalAlignAddrLValue(AddrOfExplicitObject.getPointer(), - D->getType().getNonReferenceType()); + LambdaLV = MakeAddrLValue(AddrOfExplicitObject, + D->getType().getNonReferenceType()); } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); @@ -4846,7 +4857,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // information provided by invariant.group. This is because accessing // fields may leak the real address of dynamic object, which could result // in miscompilation when leaked pointer would be compared. - auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer()); + auto *stripped = + Builder.CreateStripInvariantGroup(addr.emitRawPointer(*this)); addr = Address(stripped, addr.getElementType(), addr.getAlignment()); } } @@ -4865,10 +4877,11 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // Remember the original union field index llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(base.getType(), rec->getLocation()); - addr = Address( - Builder.CreatePreserveUnionAccessIndex( - addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), - addr.getElementType(), addr.getAlignment()); + addr = + Address(Builder.CreatePreserveUnionAccessIndex( + addr.emitRawPointer(*this), + getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), + addr.getElementType(), addr.getAlignment()); } if (FieldType->isReferenceType()) @@ -5105,11 +5118,9 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue( if (Info.LHS && Info.RHS) { Address lhsAddr = Info.LHS->getAddress(*this); Address rhsAddr = Info.RHS->getAddress(*this); - llvm::PHINode *phi = Builder.CreatePHI(lhsAddr.getType(), 2, "cond-lvalue"); - phi->addIncoming(lhsAddr.getPointer(), Info.lhsBlock); - phi->addIncoming(rhsAddr.getPointer(), Info.rhsBlock); - Address result(phi, lhsAddr.getElementType(), - std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment())); + Address result = mergeAddressesInConditionalExpr( + lhsAddr, rhsAddr, Info.lhsBlock, Info.rhsBlock, + Builder.GetInsertBlock(), expr->getType()); AlignmentSource alignSource = std::max(Info.LHS->getBaseInfo().getAlignmentSource(), Info.RHS->getBaseInfo().getAlignmentSource()); @@ -5196,7 +5207,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { LValue LV = EmitLValue(E->getSubExpr()); Address V = LV.getAddress(*this); const auto *DCE = cast(E); - return MakeNaturalAlignAddrLValue(EmitDynamicCast(V, DCE), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitDynamicCast(V, DCE), E->getType()); } case CK_ConstructorConversion: @@ -5261,8 +5272,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is // performed and the object is not of the derived type. if (sanitizePerformTypeCheck()) - EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), - Derived.getPointer(), E->getType()); + EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), Derived, + E->getType()); if (SanOpts.has(SanitizerKind::CFIDerivedCast)) EmitVTablePtrCheckForCast(E->getType(), Derived, @@ -5618,7 +5629,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { LValue CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) { - return MakeNaturalAlignAddrLValue(EmitCXXTypeidExpr(E), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitCXXTypeidExpr(E), E->getType()); } Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) { diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 5190b22bcc16..143855aa84ca 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -294,10 +294,10 @@ void AggExprEmitter::withReturnValueSlot( // Otherwise, EmitCall will emit its own, notice that it's "unused", and end // its lifetime before we have the chance to emit a proper destructor call. bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() || - (RequiresDestruction && !Dest.getAddress().isValid()); + (RequiresDestruction && Dest.isIgnored()); Address RetAddr = Address::invalid(); - Address RetAllocaAddr = Address::invalid(); + RawAddress RetAllocaAddr = RawAddress::invalid(); EHScopeStack::stable_iterator LifetimeEndBlock; llvm::Value *LifetimeSizePtr = nullptr; @@ -329,7 +329,8 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) return; - assert(Dest.isIgnored() || Dest.getPointer() != Src.getAggregatePointer()); + assert(Dest.isIgnored() || Dest.emitRawPointer(CGF) != + Src.getAggregatePointer(E->getType(), CGF)); EmitFinalDestCopy(E->getType(), Src); if (!RequiresDestruction && LifetimeStartInst) { @@ -448,7 +449,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); llvm::Value *IdxStart[] = { Zero, Zero }; llvm::Value *ArrayStart = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxStart, "arraystart"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxStart, + "arraystart"); CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); ++Field; @@ -465,7 +467,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { // End pointer. llvm::Value *IdxEnd[] = { Zero, Size }; llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxEnd, "arrayend"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd, + "arrayend"); CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { // Length. @@ -516,9 +519,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, // down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = { zero, zero }; - llvm::Value *begin = Builder.CreateInBoundsGEP( - DestPtr.getElementType(), DestPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(DestPtr.getElementType(), + DestPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); CharUnits elementAlign = @@ -1059,7 +1062,7 @@ void AggExprEmitter::VisitBinCmp(const BinaryOperator *E) { if (RV.isScalar()) return {RV.getScalarVal(), nullptr}; if (RV.isAggregate()) - return {RV.getAggregatePointer(), nullptr}; + return {RV.getAggregatePointer(E->getType(), CGF), nullptr}; assert(RV.isComplex()); return RV.getComplexVal(); }; @@ -1818,7 +1821,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // else, clean it up for -O0 builds and general tidiness. if (!pushedCleanup && LV.isSimple()) if (llvm::GetElementPtrInst *GEP = - dyn_cast(LV.getPointer(CGF))) + dyn_cast(LV.emitRawPointer(CGF))) if (GEP->use_empty()) GEP->eraseFromParent(); } @@ -1849,9 +1852,9 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, // destPtr is an array*. Construct an elementType* by drilling down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = {zero, zero}; - llvm::Value *begin = Builder.CreateInBoundsGEP( - destPtr.getElementType(), destPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getElementType(), + destPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); // Prepare to special-case multidimensional array initialization: we avoid // emitting multiple destructor loops in that case. diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 35da0f1a89bc..a4fb673284ce 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -280,7 +280,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); - This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); + This = MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(), + BaseInfo, TBAAInfo); } else { This = EmitLValue(Base); } @@ -353,10 +354,12 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (IsImplicitObjectCXXThis || isa(IOA)) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, - This.getPointer(*this), - C.getRecordType(CalleeDecl->getParent()), - /*Alignment=*/CharUnits::Zero(), SkippedChecks); + + if (sanitizePerformTypeCheck()) + EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, + This.emitRawPointer(*this), + C.getRecordType(CalleeDecl->getParent()), + /*Alignment=*/CharUnits::Zero(), SkippedChecks); // C++ [class.virtual]p12: // Explicit qualification with the scope operator (5.1) suppresses the @@ -455,7 +458,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, else This = EmitLValue(BaseExpr, KnownNonNull).getAddress(*this); - EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(), + EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), QualType(MPT->getClass(), 0)); // Get the member function pointer. @@ -1109,9 +1112,10 @@ void CodeGenFunction::EmitNewArrayInitializer( // alloca. EndOfInit = CreateTempAlloca(BeginPtr.getType(), getPointerAlign(), "array.init.end"); - CleanupDominator = Builder.CreateStore(BeginPtr.getPointer(), EndOfInit); - pushIrregularPartialArrayCleanup(BeginPtr.getPointer(), EndOfInit, - ElementType, ElementAlign, + CleanupDominator = + Builder.CreateStore(BeginPtr.emitRawPointer(*this), EndOfInit); + pushIrregularPartialArrayCleanup(BeginPtr.emitRawPointer(*this), + EndOfInit, ElementType, ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); } @@ -1123,16 +1127,17 @@ void CodeGenFunction::EmitNewArrayInitializer( // element. TODO: some of these stores can be trivially // observed to be unnecessary. if (EndOfInit.isValid()) { - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); } // FIXME: If the last initializer is an incomplete initializer list for // an array, and we have an array filler, we can fold together the two // initialization loops. StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr, AggValueSlot::DoesNotOverlap); - CurPtr = Address(Builder.CreateInBoundsGEP( - CurPtr.getElementType(), CurPtr.getPointer(), - Builder.getSize(1), "array.exp.next"), + CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(), + CurPtr.emitRawPointer(*this), + Builder.getSize(1), + "array.exp.next"), CurPtr.getElementType(), StartAlign.alignmentAtOffset((++i) * ElementSize)); } @@ -1186,7 +1191,7 @@ void CodeGenFunction::EmitNewArrayInitializer( // FIXME: Share this cleanup with the constructor call emission rather than // having it create a cleanup of its own. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Emit a constructor call loop to initialize the remaining elements. if (InitListElements) @@ -1249,15 +1254,15 @@ void CodeGenFunction::EmitNewArrayInitializer( llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end"); // Find the end of the array, hoisted out of the loop. - llvm::Value *EndPtr = - Builder.CreateInBoundsGEP(BeginPtr.getElementType(), BeginPtr.getPointer(), - NumElements, "array.end"); + llvm::Value *EndPtr = Builder.CreateInBoundsGEP( + BeginPtr.getElementType(), BeginPtr.emitRawPointer(*this), NumElements, + "array.end"); // If the number of elements isn't constant, we have to now check if there is // anything left to initialize. if (!ConstNum) { - llvm::Value *IsEmpty = - Builder.CreateICmpEQ(CurPtr.getPointer(), EndPtr, "array.isempty"); + llvm::Value *IsEmpty = Builder.CreateICmpEQ(CurPtr.emitRawPointer(*this), + EndPtr, "array.isempty"); Builder.CreateCondBr(IsEmpty, ContBB, LoopBB); } @@ -1267,19 +1272,20 @@ void CodeGenFunction::EmitNewArrayInitializer( // Set up the current-element phi. llvm::PHINode *CurPtrPhi = Builder.CreatePHI(CurPtr.getType(), 2, "array.cur"); - CurPtrPhi->addIncoming(CurPtr.getPointer(), EntryBB); + CurPtrPhi->addIncoming(CurPtr.emitRawPointer(*this), EntryBB); CurPtr = Address(CurPtrPhi, CurPtr.getElementType(), ElementAlign); // Store the new Cleanup position for irregular Cleanups. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Enter a partial-destruction Cleanup if necessary. if (!CleanupDominator && needsEHCleanup(DtorKind)) { - pushRegularPartialArrayCleanup(BeginPtr.getPointer(), CurPtr.getPointer(), - ElementType, ElementAlign, - getDestroyer(DtorKind)); + llvm::Value *BeginPtrRaw = BeginPtr.emitRawPointer(*this); + llvm::Value *CurPtrRaw = CurPtr.emitRawPointer(*this); + pushRegularPartialArrayCleanup(BeginPtrRaw, CurPtrRaw, ElementType, + ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); CleanupDominator = Builder.CreateUnreachable(); } @@ -1295,9 +1301,8 @@ void CodeGenFunction::EmitNewArrayInitializer( } // Advance to the next element by adjusting the pointer type as necessary. - llvm::Value *NextPtr = - Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr.getPointer(), 1, - "array.next"); + llvm::Value *NextPtr = Builder.CreateConstInBoundsGEP1_32( + ElementTy, CurPtr.emitRawPointer(*this), 1, "array.next"); // Check whether we've gotten to the end of the array and, if so, // exit the loop. @@ -1523,14 +1528,9 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, typedef CallDeleteDuringNew DirectCleanup; - DirectCleanup *Cleanup = CGF.EHStack - .pushCleanupWithExtra(EHCleanup, - E->getNumPlacementArgs(), - E->getOperatorDelete(), - NewPtr.getPointer(), - AllocSize, - E->passAlignment(), - AllocAlign); + DirectCleanup *Cleanup = CGF.EHStack.pushCleanupWithExtra( + EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(), + NewPtr.emitRawPointer(CGF), AllocSize, E->passAlignment(), AllocAlign); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { auto &Arg = NewArgs[I + NumNonPlacementArgs]; Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty); @@ -1541,7 +1541,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, // Otherwise, we need to save all this stuff. DominatingValue::saved_type SavedNewPtr = - DominatingValue::save(CGF, RValue::get(NewPtr.getPointer())); + DominatingValue::save(CGF, RValue::get(NewPtr, CGF)); DominatingValue::saved_type SavedAllocSize = DominatingValue::save(CGF, RValue::get(AllocSize)); @@ -1618,14 +1618,14 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // In these cases, discard the computed alignment and use the // formal alignment of the allocated type. if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl) - allocation = allocation.withAlignment(allocAlign); + allocation.setAlignment(allocAlign); // Set up allocatorArgs for the call to operator delete if it's not // the reserved global operator. if (E->getOperatorDelete() && !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType()); - allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType()); + allocatorArgs.add(RValue::get(allocation, *this), arg->getType()); } } else { @@ -1713,8 +1713,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull"); contBB = createBasicBlock("new.cont"); - llvm::Value *isNull = - Builder.CreateIsNull(allocation.getPointer(), "new.isnull"); + llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull"); Builder.CreateCondBr(isNull, contBB, notNullBB); EmitBlock(notNullBB); } @@ -1760,12 +1759,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { SkippedChecks.set(SanitizerKind::Null, nullCheck); EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(), - result.getPointer(), allocType, result.getAlignment(), - SkippedChecks, numElements); + result, allocType, result.getAlignment(), SkippedChecks, + numElements); EmitNewInitializer(*this, E, allocType, elementTy, result, numElements, allocSizeWithoutCookie); - llvm::Value *resultPtr = result.getPointer(); + llvm::Value *resultPtr = result.emitRawPointer(*this); if (E->isArray()) { // NewPtr is a pointer to the base element type. If we're // allocating an array of arrays, we'll need to cast back to the @@ -1909,7 +1908,8 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, Dtor); else - CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType); + CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.emitRawPointer(CGF), + ElementType); } /// Emit the code for deleting a single object. @@ -1925,8 +1925,7 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // dynamic type, the static type shall be a base class of the dynamic type // of the object to be deleted and the static type shall have a virtual // destructor or the behavior is undefined. - CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, - DE->getExprLoc(), Ptr.getPointer(), + CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, DE->getExprLoc(), Ptr, ElementType); const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); @@ -1975,9 +1974,8 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // Make sure that we call delete even if the dtor throws. // This doesn't have to a conditional cleanup because we're going // to pop it off in a second. - CGF.EHStack.pushCleanup(NormalAndEHCleanup, - Ptr.getPointer(), - OperatorDelete, ElementType); + CGF.EHStack.pushCleanup( + NormalAndEHCleanup, Ptr.emitRawPointer(CGF), OperatorDelete, ElementType); if (Dtor) CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, @@ -2064,7 +2062,7 @@ static void EmitArrayDelete(CodeGenFunction &CGF, CharUnits elementAlign = deletedPtr.getAlignment().alignmentOfArrayElement(elementSize); - llvm::Value *arrayBegin = deletedPtr.getPointer(); + llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF); llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP( deletedPtr.getElementType(), arrayBegin, numElements, "delete.end"); @@ -2095,7 +2093,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); - llvm::Value *IsNull = Builder.CreateIsNull(Ptr.getPointer(), "isnull"); + llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull"); Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); @@ -2130,10 +2128,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { GEP.push_back(Zero); } - Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getElementType(), - Ptr.getPointer(), GEP, "del.first"), - ConvertTypeForMem(DeleteTy), Ptr.getAlignment(), - Ptr.isKnownNonNull()); + Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, ConvertTypeForMem(DeleteTy), + Ptr.getAlignment(), "del.first"); } assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); @@ -2191,7 +2187,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, // destruction and the static type of the operand is neither the constructor // or destructor’s class nor one of its bases, the behavior is undefined. CGF.EmitTypeCheck(CodeGenFunction::TCK_DynamicOperation, E->getExprLoc(), - ThisPtr.getPointer(), SrcRecordTy); + ThisPtr, SrcRecordTy); // C++ [expr.typeid]p2: // If the glvalue expression is obtained by applying the unary * operator to @@ -2207,7 +2203,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, CGF.createBasicBlock("typeid.bad_typeid"); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end"); - llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr.getPointer()); + llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr); CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock); CGF.EmitBlock(BadTypeidBlock); @@ -2293,8 +2289,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, // construction or destruction and the static type of the operand is not a // pointer to or object of the constructor or destructor’s own class or one // of its bases, the dynamic_cast results in undefined behavior. - EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr.getPointer(), - SrcRecordTy); + EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr, SrcRecordTy); if (DCE->isAlwaysNull()) { if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy)) { @@ -2329,7 +2324,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, CastNull = createBasicBlock("dynamic_cast.null"); CastNotNull = createBasicBlock("dynamic_cast.notnull"); - llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 67a3cdc77042..36d7493d9a6b 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -800,8 +800,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, // Add a vtable pointer, if we need one and it hasn't already been added. if (Layout.hasOwnVFPtr()) { llvm::Constant *VTableAddressPoint = - CGM.getCXXABI().getVTableAddressPointForConstExpr( - BaseSubobject(CD, Offset), VTableClass); + CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset), + VTableClass); if (!AppendBytes(Offset, VTableAddressPoint)) return false; } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 8536570087ad..83247aa48f86 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2250,7 +2250,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { // performed and the object is not of the derived type. if (CGF.sanitizePerformTypeCheck()) CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(), - Derived.getPointer(), DestTy->getPointeeType()); + Derived, DestTy->getPointeeType()); if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast)) CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived, @@ -2258,13 +2258,14 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { CodeGenFunction::CFITCK_DerivedCast, CE->getBeginLoc()); - return Derived.getPointer(); + return CGF.getAsNaturalPointerTo(Derived, CE->getType()->getPointeeType()); } case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { // The EmitPointerWithAlignment path does this fine; just discard // the alignment. - return CGF.EmitPointerWithAlignment(CE).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitPointerWithAlignment(CE), + CE->getType()->getPointeeType()); } case CK_Dynamic: { @@ -2274,7 +2275,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } case CK_ArrayToPointerDecay: - return CGF.EmitArrayToPointerDecay(E).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitArrayToPointerDecay(E), + CE->getType()->getPointeeType()); case CK_FunctionToPointerDecay: return EmitLValue(E).getPointer(CGF); @@ -5588,3 +5590,16 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr, return GEPVal; } + +Address CodeGenFunction::EmitCheckedInBoundsGEP( + Address Addr, ArrayRef IdxList, llvm::Type *elementType, + bool SignedIndices, bool IsSubtraction, SourceLocation Loc, CharUnits Align, + const Twine &Name) { + if (!SanOpts.has(SanitizerKind::PointerOverflow)) + return Builder.CreateInBoundsGEP(Addr, IdxList, elementType, Align, Name); + + return RawAddress( + EmitCheckedInBoundsGEP(Addr.getElementType(), Addr.emitRawPointer(*this), + IdxList, SignedIndices, IsSubtraction, Loc, Name), + elementType, Align); +} diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 75c1d7fbea84..8fade0fac21e 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -366,7 +366,7 @@ template struct GenFuncBase { llvm::Value *SizeInBytes = CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP( - CGF.Int8Ty, DstAddr.getPointer(), SizeInBytes); + CGF.Int8Ty, DstAddr.emitRawPointer(CGF), SizeInBytes); llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); // Create the header block and insert the phi instructions. @@ -376,7 +376,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); - PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); + PHIs[I]->addIncoming(StartAddrs[I].emitRawPointer(CGF), PreheaderBB); } // Create the exit and loop body blocks. @@ -410,7 +410,7 @@ template struct GenFuncBase { // Instrs to update the destination and source addresses. // Update phi instructions. NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); - PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); + PHIs[I]->addIncoming(NewAddrs[I].emitRawPointer(CGF), LoopBB); } // Insert an unconditional branch to the header block. @@ -488,7 +488,7 @@ template struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { Alignments[I] = Addrs[I].getAlignment(); - Ptrs[I] = Addrs[I].getPointer(); + Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF); } if (llvm::Function *F = diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index f3a948cf13f9..c7f497a7c845 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -94,8 +94,8 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { // and cast value to correct type Address Temporary = CreateMemTemp(SubExpr->getType()); EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); - llvm::Value *BitCast = - Builder.CreateBitCast(Temporary.getPointer(), ConvertType(ArgQT)); + llvm::Value *BitCast = Builder.CreateBitCast( + Temporary.emitRawPointer(*this), ConvertType(ArgQT)); Args.add(RValue::get(BitCast), ArgQT); // Create char array to store type encoding @@ -204,11 +204,11 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); const ParmVarDecl *argDecl = *PI++; QualType ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Objects.getPointer()), ArgQT); + Args.add(RValue::get(Objects, *this), ArgQT); if (DLE) { argDecl = *PI++; ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Keys.getPointer()), ArgQT); + Args.add(RValue::get(Keys, *this), ArgQT); } argDecl = *PI; ArgQT = argDecl->getType().getUnqualifiedType(); @@ -827,7 +827,7 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, // sizeof (Type of Ivar), isAtomic, false); CallArgList args; - llvm::Value *dest = CGF.ReturnValue.getPointer(); + llvm::Value *dest = CGF.ReturnValue.emitRawPointer(CGF); args.add(RValue::get(dest), Context.VoidPtrTy); args.add(RValue::get(src), Context.VoidPtrTy); @@ -1147,8 +1147,8 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, callCStructCopyConstructor(Dst, Src); } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), ivar, - AtomicHelperFn); + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), + ivar, AtomicHelperFn); } return; } @@ -1163,7 +1163,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), ivar, AtomicHelperFn); } return; @@ -1287,7 +1287,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { - value = LV.getAddress(*this).getPointer(); + value = LV.getAddress(*this).emitRawPointer(*this); } else { // We want to load and autoreleaseReturnValue ARC __weak ivars. if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { @@ -1821,16 +1821,14 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ CallArgList Args; // The first argument is a temporary of the enumeration-state type. - Args.add(RValue::get(StatePtr.getPointer()), - getContext().getPointerType(StateTy)); + Args.add(RValue::get(StatePtr, *this), getContext().getPointerType(StateTy)); // The second argument is a temporary array with space for NumItems // pointers. We'll actually be loading elements from the array // pointer written into the control state; this buffer is so that // collections that *aren't* backed by arrays can still queue up // batches of elements. - Args.add(RValue::get(ItemsPtr.getPointer()), - getContext().getPointerType(ItemsTy)); + Args.add(RValue::get(ItemsPtr, *this), getContext().getPointerType(ItemsTy)); // The third argument is the capacity of that temporary array. llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType()); @@ -2198,7 +2196,7 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr, if (!fn) fn = getARCIntrinsic(IntID, CGF.CGM); - return CGF.EmitNounwindRuntimeCall(fn, addr.getPointer()); + return CGF.EmitNounwindRuntimeCall(fn, addr.emitRawPointer(CGF)); } /// Perform an operation having the following signature: @@ -2216,9 +2214,8 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr, llvm::Type *origType = value->getType(); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(addr.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy) - }; + CGF.Builder.CreateBitCast(addr.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy)}; llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2237,9 +2234,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src, fn = getARCIntrinsic(IntID, CGF.CGM); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(src.getPointer(), CGF.Int8PtrPtrTy) - }; + CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(src.emitRawPointer(CGF), CGF.Int8PtrPtrTy)}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2490,9 +2486,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr, fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM); llvm::Value *args[] = { - Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy), - Builder.CreateBitCast(value, Int8PtrTy) - }; + Builder.CreateBitCast(addr.emitRawPointer(*this), Int8PtrPtrTy), + Builder.CreateBitCast(value, Int8PtrTy)}; EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2643,7 +2638,7 @@ void CodeGenFunction::EmitARCDestroyWeak(Address addr) { if (!fn) fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM); - EmitNounwindRuntimeCall(fn, addr.getPointer()); + EmitNounwindRuntimeCall(fn, addr.emitRawPointer(*this)); } /// void \@objc_moveWeak(i8** %dest, i8** %src) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index a36b0cdddaf0..4e7f777ba1d9 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -706,7 +706,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd}; + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -761,8 +762,8 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::FunctionCallee LookupFn = SlotLookupFn; // Store the receiver on the stack so that we can reload it later - Address ReceiverPtr = - CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); + RawAddress ReceiverPtr = + CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); Builder.CreateStore(Receiver, ReceiverPtr); llvm::Value *self; @@ -778,9 +779,9 @@ class CGObjCGNUstep : public CGObjCGNU { LookupFn2->addParamAttr(0, llvm::Attribute::NoCapture); llvm::Value *args[] = { - EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy) }; + EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy)}; llvm::CallBase *slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args); slot->setOnlyReadsMemory(); slot->setMetadata(msgSendMDKind, node); @@ -800,7 +801,7 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd}; + llvm::Value *lookupArgs[] = {ObjCSuper.emitRawPointer(CGF), cmd}; llvm::CallInst *slot = CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs); @@ -1221,10 +1222,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { llvm::Value *cmd, MessageSendInfo &MSI) override { // Don't access the slot unless we're trying to cache the result. CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, - ObjCSuper.getPointer(), - PtrToObjCSuperTy), - cmd}; + llvm::Value *lookupArgs[] = { + CGObjCGNU::EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), + PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -2186,7 +2187,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd, + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd, }; if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) @@ -4201,15 +4203,15 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF, Address AddrWeakObj) { CGBuilderTy &B = CGF.Builder; - return B.CreateCall(WeakReadFn, - EnforceType(B, AddrWeakObj.getPointer(), PtrToIdTy)); + return B.CreateCall( + WeakReadFn, EnforceType(B, AddrWeakObj.emitRawPointer(CGF), PtrToIdTy)); } void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(WeakAssignFn, {src, dstVal}); } @@ -4218,7 +4220,7 @@ void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF, bool threadlocal) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); // FIXME. Add threadloca assign API assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI"); B.CreateCall(GlobalAssignFn, {src, dstVal}); @@ -4229,7 +4231,7 @@ void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *ivarOffset) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), IdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), IdTy); B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset}); } @@ -4237,7 +4239,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(StrongCastAssignFn, {src, dstVal}); } @@ -4246,8 +4248,8 @@ void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address SrcPtr, llvm::Value *Size) { CGBuilderTy &B = CGF.Builder; - llvm::Value *DestPtrVal = EnforceType(B, DestPtr.getPointer(), PtrTy); - llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.getPointer(), PtrTy); + llvm::Value *DestPtrVal = EnforceType(B, DestPtr.emitRawPointer(CGF), PtrTy); + llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.emitRawPointer(CGF), PtrTy); B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal, Size}); } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index ed8d7b9a065d..8a599c10e1ca 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1310,7 +1310,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); public: CGObjCMac(CodeGen::CodeGenModule &cgm); @@ -1538,7 +1538,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C /// interface. The return value has type EHTypePtrTy. @@ -2064,9 +2064,8 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, const ObjCMethodDecl *Method) { // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, @@ -4259,7 +4258,7 @@ namespace { CGF.EmitBlock(FinallyCallExit); CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); CGF.EmitBlock(FinallyNoCallExit); @@ -4425,7 +4424,9 @@ void FragileHazards::emitHazardsInNewBlocks() { } static void addIfPresent(llvm::DenseSet &S, Address V) { - if (V.isValid()) S.insert(V.getPointer()); + if (V.isValid()) + if (llvm::Value *Ptr = V.getBasePointer()) + S.insert(Ptr); } void FragileHazards::collectLocals() { @@ -4628,13 +4629,13 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // - Call objc_exception_try_enter to push ExceptionData on top of // the EH stack. CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); // - Call setjmp on the exception data buffer. llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( - ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes, + ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes, "setjmp_buffer"); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); @@ -4673,9 +4674,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, } else { // Retrieve the exception object. We may emit multiple blocks but // nothing can cross this so the value is already in SSA form. - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); // Push the exception to rethrow onto the EH value stack for the // benefit of any @throws in the handlers. @@ -4698,7 +4699,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Enter a new exception try block (in case a @catch block // throws an exception). CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), @@ -4829,9 +4830,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Extract the new exception and save it to the // propagating-exception slot. assert(PropagatingExnVar.isValid()); - llvm::CallInst *NewCaught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *NewCaught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); // Don't pop the catch handler; the throw already did. @@ -4861,9 +4862,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Otherwise, just look in the buffer for the exception to throw. } else { - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer()); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF)); PropagatingExn = Caught; } @@ -4906,7 +4906,7 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, Address AddrWeakObj) { llvm::Type* DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -4928,8 +4928,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = { src, dstVal }; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -4950,8 +4950,8 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), @@ -4977,8 +4977,8 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -4997,8 +4997,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "strongassign"); @@ -5007,7 +5007,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -5243,7 +5244,7 @@ llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel)); } -Address CGObjCMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) { CharUnits Align = CGM.getPointerAlign(); llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; @@ -5254,7 +5255,7 @@ Address CGObjCMac::EmitSelectorAddr(Selector Sel) { Entry->setExternallyInitialized(true); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { @@ -7323,7 +7324,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, ObjCTypes.MessageRefTy, CGF.getPointerAlign()); // Update the message ref argument. - args[1].setRValue(RValue::get(mref.getPointer())); + args[1].setRValue(RValue::get(mref, CGF)); // Load the function to call from the message ref table. Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0); @@ -7552,9 +7553,8 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // ... // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); @@ -7594,7 +7594,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, return LI; } -Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; CharUnits Align = CGM.getPointerAlign(); if (!Entry) { @@ -7610,7 +7610,7 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { CGM.addCompilerUsedGlobal(Entry); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. @@ -7629,8 +7629,8 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -7650,8 +7650,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "weakassign"); @@ -7660,7 +7660,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *Size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), Size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -7672,7 +7673,7 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( Address AddrWeakObj) { llvm::Type *DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -7694,8 +7695,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -7716,8 +7717,8 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 424564f97599..01d0f35da196 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -67,7 +67,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr"); if (!Ivar->isBitField()) { - LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(V, IvarTy); return LV; } @@ -233,7 +233,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI(); if (auto *CPI = dyn_cast_or_null(CPICandidate)) { CGF.CurrentFuncletPad = CPI; - CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); + CPI->setOperand(2, CGF.getExceptionSlot().emitRawPointer(CGF)); CGF.EHStack.pushCleanup(NormalCleanup, CPI); } } @@ -405,7 +405,7 @@ bool CGObjCRuntime::canMessageReceiverBeNull(CodeGenFunction &CGF, auto self = curMethod->getSelfDecl(); if (self->getType().isConstQualified()) { if (auto LI = dyn_cast(receiver->stripPointerCasts())) { - llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).getPointer(); + llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).emitRawPointer(CGF); if (selfAddr == LI->getPointerOperand()) { return false; } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 00e395c2a207..bc363313dec6 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -622,7 +622,7 @@ static void emitInitWithReductionInitializer(CodeGenFunction &CGF, auto *GV = new llvm::GlobalVariable( CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Init, Name); - LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(GV, Ty); RValue InitRVal; switch (CGF.getEvaluationKind(Ty)) { case TEK_Scalar: @@ -668,8 +668,8 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, llvm::Value *SrcBegin = nullptr; if (DRD) - SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + SrcBegin = SrcAddr.emitRawPointer(CGF); + llvm::Value *DestBegin = DestAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -912,7 +912,7 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr) { - Address Tmp = Address::invalid(); + RawAddress Tmp = RawAddress::invalid(); Address TopTmp = Address::invalid(); Address MostTopTmp = Address::invalid(); BaseTy = BaseTy.getNonReferenceType(); @@ -971,10 +971,10 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( SharedAddr.getElementType(), BaseLValue.getPointer(CGF), - SharedAddr.getPointer()); + SharedAddr.emitRawPointer(CGF)); llvm::Value *PrivatePointer = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivateAddr.getPointer(), SharedAddr.getType()); + PrivateAddr.emitRawPointer(CGF), SharedAddr.getType()); llvm::Value *Ptr = CGF.Builder.CreateGEP( SharedAddr.getElementType(), PrivatePointer, Adjustment); return castToBase(CGF, OrigVD->getType(), @@ -1557,7 +1557,7 @@ static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc( return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName); } -Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { +ConstantAddress CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; auto LinkageForVariable = [&VD, this]() { @@ -1579,8 +1579,8 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { LinkageForVariable); if (!addr) - return Address::invalid(); - return Address(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); + return ConstantAddress::invalid(); + return ConstantAddress(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); } llvm::Constant * @@ -1604,7 +1604,7 @@ Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy), + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy), CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), getOrCreateThreadPrivateCache(VD)}; return Address( @@ -1627,7 +1627,8 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit( // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) // to register constructor/destructor for variable. llvm::Value *Args[] = { - OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), + OMPLoc, + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.VoidPtrTy), Ctor, CopyCtor, Dtor}; CGF.EmitRuntimeCall( OMPBuilder.getOrCreateRuntimeFunction( @@ -1900,13 +1901,13 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, // OutlinedFn(>id, &zero_bound, CapturedStruct); Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); - Address ZeroAddrBound = + RawAddress ZeroAddrBound = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".bound.zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddrBound); llvm::SmallVector OutlinedFnArgs; // ThreadId for serialized parallels is 0. - OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); + OutlinedFnArgs.push_back(ThreadIDAddr.emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); @@ -2272,7 +2273,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, emitUpdateLocation(CGF, Loc), // ident_t * getThreadID(CGF, Loc), // i32 BufSize, // size_t - CL.getPointer(), // void * + CL.emitRawPointer(CGF), // void * CpyFn, // void (*) (void *, void *) DidItVal // i32 did_it }; @@ -2591,10 +2592,10 @@ static void emitForStaticInitCall( ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, M2)), // Schedule type - Values.IL.getPointer(), // &isLastIter - Values.LB.getPointer(), // &LB - Values.UB.getPointer(), // &UB - Values.ST.getPointer(), // &Stride + Values.IL.emitRawPointer(CGF), // &isLastIter + Values.LB.emitRawPointer(CGF), // &LB + Values.UB.emitRawPointer(CGF), // &UB + Values.ST.emitRawPointer(CGF), // &Stride CGF.Builder.getIntN(Values.IVSize, 1), // Incr Chunk // Chunk }; @@ -2697,12 +2698,11 @@ llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, // kmp_int[32|64] *p_stride); llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), - IL.getPointer(), // &isLastIter - LB.getPointer(), // &Lower - UB.getPointer(), // &Upper - ST.getPointer() // &Stride + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + IL.emitRawPointer(CGF), // &isLastIter + LB.emitRawPointer(CGF), // &Lower + UB.emitRawPointer(CGF), // &Upper + ST.emitRawPointer(CGF) // &Stride }; llvm::Value *Call = CGF.EmitRuntimeCall( OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args); @@ -3047,7 +3047,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, CGF.Builder .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF), CGF.VoidPtrTy, CGF.Int8Ty) - .getPointer()}; + .emitRawPointer(CGF)}; SmallVector CallArgs(std::begin(CommonArgs), std::end(CommonArgs)); if (isOpenMPTaskLoopDirective(Kind)) { @@ -3574,7 +3574,8 @@ getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); Address UpAddrAddress = UpAddrLVal.getAddress(CGF); llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( - UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); + UpAddrAddress.getElementType(), UpAddrAddress.emitRawPointer(CGF), + /*Idx0=*/1); llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); @@ -3888,8 +3889,9 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Size; std::tie(Addr, Size) = getPointerAndSize(CGF, E); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - LValue Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(AffinitiesArray, Idx), KmpTaskAffinityInfoTy); + LValue Base = + CGF.MakeAddrLValue(CGF.Builder.CreateGEP(CGF, AffinitiesArray, Idx), + KmpTaskAffinityInfoTy); // affs[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); @@ -3910,7 +3912,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); llvm::Value *GTid = getThreadID(CGF, Loc); llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - AffinitiesArray.getPointer(), CGM.VoidPtrTy); + AffinitiesArray.emitRawPointer(CGF), CGM.VoidPtrTy); // FIXME: Emit the function and ignore its result for now unless the // runtime function is properly implemented. (void)CGF.EmitRuntimeCall( @@ -3921,8 +3923,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( NewTask, KmpTaskTWithPrivatesPtrTy); - LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, - KmpTaskTWithPrivatesQTy); + LValue Base = CGF.MakeNaturalAlignRawAddrLValue(NewTaskNewTaskTTy, + KmpTaskTWithPrivatesQTy); LValue TDBase = CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); // Fill the data in the resulting kmp_task_t record. @@ -4047,7 +4049,7 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, CGF.ConvertTypeForMem(KmpDependInfoPtrTy)), KmpDependInfoPtrTy->castAs()); Address DepObjAddr = CGF.Builder.CreateGEP( - Base.getAddress(CGF), + CGF, Base.getAddress(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4097,7 +4099,7 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue &PosLVal = *Pos.get(); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(DependenciesArray, Idx), KmpDependInfoTy); + CGF.Builder.CreateGEP(CGF, DependenciesArray, Idx), KmpDependInfoTy); } // deps[i].base_addr = &; LValue BaseAddrLVal = CGF.EmitLValueForField( @@ -4195,7 +4197,7 @@ void CGOpenMPRuntime::emitDepobjElements(CodeGenFunction &CGF, ElSize, CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - Address DepAddr = CGF.Builder.CreateGEP(DependenciesArray, Pos); + Address DepAddr = CGF.Builder.CreateGEP(CGF, DependenciesArray, Pos); CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); // Increase pos. @@ -4430,7 +4432,7 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), CGF.ConvertTypeForMem(KmpDependInfoTy)); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getElementType(), Addr.getPointer(), + Addr.getElementType(), Addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, CGF.VoidPtrTy); @@ -4460,8 +4462,8 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, Address Begin = Base.getAddress(CGF); // Cast from pointer to array type to pointer to single element. - llvm::Value *End = CGF.Builder.CreateGEP( - Begin.getElementType(), Begin.getPointer(), NumDeps); + llvm::Value *End = CGF.Builder.CreateGEP(Begin.getElementType(), + Begin.emitRawPointer(CGF), NumDeps); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); @@ -4469,7 +4471,7 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, CGF.EmitBlock(BodyBB); llvm::PHINode *ElementPHI = CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); - ElementPHI->addIncoming(Begin.getPointer(), EntryBB); + ElementPHI->addIncoming(Begin.emitRawPointer(CGF), EntryBB); Begin = Begin.withPointer(ElementPHI, KnownNonNull); Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4483,12 +4485,12 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, FlagsLVal); // Shift the address forward by one element. - Address ElementNext = - CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); - ElementPHI->addIncoming(ElementNext.getPointer(), - CGF.Builder.GetInsertBlock()); + llvm::Value *ElementNext = + CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext") + .emitRawPointer(CGF); + ElementPHI->addIncoming(ElementNext, CGF.Builder.GetInsertBlock()); llvm::Value *IsEmpty = - CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); + CGF.Builder.CreateICmpEQ(ElementNext, End, "omp.isempty"); CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); // Done. CGF.EmitBlock(DoneBB, /*IsFinished=*/true); @@ -4531,7 +4533,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepTaskArgs[1] = ThreadID; DepTaskArgs[2] = NewTask; DepTaskArgs[3] = NumOfElements; - DepTaskArgs[4] = DependenciesArray.getPointer(); + DepTaskArgs[4] = DependenciesArray.emitRawPointer(CGF); DepTaskArgs[5] = CGF.Builder.getInt32(0); DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); } @@ -4563,7 +4565,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -4725,8 +4727,8 @@ static void EmitOMPAggregateReduction( const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); - llvm::Value *RHSBegin = RHSAddr.getPointer(); - llvm::Value *LHSBegin = LHSAddr.getPointer(); + llvm::Value *RHSBegin = RHSAddr.emitRawPointer(CGF); + llvm::Value *LHSBegin = LHSAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); @@ -4990,7 +4992,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, QualType ReductionArrayTy = C.getConstantArrayType( C.VoidPtrTy, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); const auto *IPriv = Privates.begin(); unsigned Idx = 0; @@ -5462,7 +5464,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( C.getConstantArrayType(RDType, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); // kmp_task_red_input_t .rd_input.[Size]; - Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); + RawAddress TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, Data.ReductionCopies, Data.ReductionOps); for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { @@ -5473,7 +5475,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( TaskRedInput.getElementType(), TaskRedInput.getPointer(), Idxs, /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, ".rd_input.gep."); - LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); + LValue ElemLVal = CGF.MakeNaturalAlignRawAddrLValue(GEP, RDType); // ElemLVal.reduce_shar = &Shareds[Cnt]; LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); RCG.emitSharedOrigLValue(CGF, Cnt); @@ -5629,7 +5631,7 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -5852,7 +5854,7 @@ void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, AllocatorTraitsLVal.getBaseInfo(), AllocatorTraitsLVal.getTBAAInfo()); - llvm::Value *Traits = Addr.getPointer(); + llvm::Value *Traits = Addr.emitRawPointer(CGF); llvm::Value *AllocatorVal = CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -7312,17 +7314,19 @@ private: CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) .getAddress(CGF); } - Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, ComponentLB.getPointer(), LB.getPointer()); + llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); + Size = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, + LBPtr); break; } } assert(Size && "Failed to determine structure size"); CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7332,13 +7336,14 @@ private: LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); } CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).getPointer(), - LB.getPointer()); + CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF), + LBPtr); CombinedInfo.Sizes.push_back( CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7356,20 +7361,21 @@ private: (Next == CE && MapType != OMPC_MAP_unknown)) { if (!IsMappingWholeStruct) { CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1); } else { StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - StructBaseCombinedInfo.BasePointers.push_back(BP.getPointer()); + StructBaseCombinedInfo.BasePointers.push_back( + BP.emitRawPointer(CGF)); StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr); StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - StructBaseCombinedInfo.Pointers.push_back(LB.getPointer()); + StructBaseCombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); StructBaseCombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); StructBaseCombinedInfo.NonContigInfo.Dims.push_back( @@ -8211,11 +8217,11 @@ public: } CombinedInfo.Exprs.push_back(VD); // Base is the base of the struct - CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); // Pointer is the address of the lowest element - llvm::Value *LB = LBAddr.getPointer(); + llvm::Value *LB = LBAddr.emitRawPointer(CGF); const CXXMethodDecl *MD = CGF.CurFuncDecl ? dyn_cast(CGF.CurFuncDecl) : nullptr; const CXXRecordDecl *RD = MD ? MD->getParent() : nullptr; @@ -8229,7 +8235,7 @@ public: // if the this[:1] expression had appeared in a map clause with a map-type // of tofrom. // Emit this[:1] - CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); QualType Ty = MD->getFunctionObjectParameterType(); llvm::Value *Size = CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty, @@ -8238,7 +8244,7 @@ public: } else { CombinedInfo.Pointers.push_back(LB); // Size is (addr of {highest+1} element) - (addr of lowest element) - llvm::Value *HB = HBAddr.getPointer(); + llvm::Value *HB = HBAddr.emitRawPointer(CGF); llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32( HBAddr.getElementType(), HB, /*Idx0=*/1); llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); @@ -8747,7 +8753,7 @@ public: Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( CV, ElementType, CGF.getContext().getDeclAlign(VD), AlignmentSource::Decl)); - CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); + CombinedInfo.Pointers.push_back(PtrAddr.emitRawPointer(CGF)); } else { CombinedInfo.Pointers.push_back(CV); } @@ -9558,10 +9564,11 @@ static void emitTargetCallKernelLaunch( bool HasNoWait = D.hasClausesOfKind(); unsigned NumTargetItems = InputInfo.NumberOfTargetItems; - llvm::Value *BasePointersArray = InputInfo.BasePointersArray.getPointer(); - llvm::Value *PointersArray = InputInfo.PointersArray.getPointer(); - llvm::Value *SizesArray = InputInfo.SizesArray.getPointer(); - llvm::Value *MappersArray = InputInfo.MappersArray.getPointer(); + llvm::Value *BasePointersArray = + InputInfo.BasePointersArray.emitRawPointer(CGF); + llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF); + llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF); + llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF); auto &&EmitTargetCallFallbackCB = [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS, @@ -10309,15 +10316,16 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( // Source location for the ident struct llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); - llvm::Value *OffloadingArgs[] = {RTLoc, - DeviceID, - PointerNum, - InputInfo.BasePointersArray.getPointer(), - InputInfo.PointersArray.getPointer(), - InputInfo.SizesArray.getPointer(), - MapTypesArray, - MapNamesArray, - InputInfo.MappersArray.getPointer()}; + llvm::Value *OffloadingArgs[] = { + RTLoc, + DeviceID, + PointerNum, + InputInfo.BasePointersArray.emitRawPointer(CGF), + InputInfo.PointersArray.emitRawPointer(CGF), + InputInfo.SizesArray.emitRawPointer(CGF), + MapTypesArray, + MapNamesArray, + InputInfo.MappersArray.emitRawPointer(CGF)}; // Select the right runtime function call for each standalone // directive. @@ -11128,7 +11136,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, getThreadID(CGF, D.getBeginLoc()), llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), + CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).emitRawPointer(CGF), CGM.VoidPtrTy)}; llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( @@ -11162,7 +11170,8 @@ static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, /*Volatile=*/false, Int64Ty); } llvm::Value *Args[] = { - ULoc, ThreadID, CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; + ULoc, ThreadID, + CGF.Builder.CreateConstArrayGEP(CntAddr, 0).emitRawPointer(CGF)}; llvm::FunctionCallee RTLFn; llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); OMPDoacrossKind ODK; @@ -11332,7 +11341,7 @@ Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( CGF, SourceLocation::getFromRawEncoding(LocEncoding)); Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - Addr.getPointer(), CGF.VoidPtrTy); + Addr.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *AllocVal = getAllocatorVal(CGF, AllocExpr); Args[2] = AllocVal; CGF.EmitRuntimeCall(RTLFn, Args); @@ -11690,15 +11699,17 @@ void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LLIVTy, getName({UniqueDeclName, "iv"})); cast(LastIV)->setAlignment( IVLVal.getAlignment().getAsAlign()); - LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); + LValue LastIVLVal = + CGF.MakeNaturalAlignRawAddrLValue(LastIV, IVLVal.getType()); // Last value of the lastprivate conditional. // decltype(priv_a) last_a; llvm::GlobalVariable *Last = OMPBuilder.getOrCreateInternalVariable( CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); - Last->setAlignment(LVal.getAlignment().getAsAlign()); - LValue LastLVal = CGF.MakeAddrLValue( - Address(Last, Last->getValueType(), LVal.getAlignment()), LVal.getType()); + cast(Last)->setAlignment( + LVal.getAlignment().getAsAlign()); + LValue LastLVal = + CGF.MakeRawAddrLValue(Last, LVal.getType(), LVal.getAlignment()); // Global loop counter. Required to handle inner parallel-for regions. // iv @@ -11871,9 +11882,8 @@ void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( // The variable was not updated in the region - exit. if (!GV) return; - LValue LPLVal = CGF.MakeAddrLValue( - Address(GV, GV->getValueType(), PrivLVal.getAlignment()), - PrivLVal.getType().getNonReferenceType()); + LValue LPLVal = CGF.MakeRawAddrLValue( + GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); CGF.EmitStoreOfScalar(Res, PrivLVal); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index c3206427b143..522ae3d35d22 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1068,13 +1068,12 @@ public: /// \param Loc Location of the reference to threadprivate var. /// \return Address of the threadprivate variable for the current thread. virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, - Address VDAddr, + const VarDecl *VD, Address VDAddr, SourceLocation Loc); /// Returns the address of the variable marked as declare target with link /// clause OR as declare target with to clause and unified memory. - virtual Address getAddrOfDeclareTargetVar(const VarDecl *VD); + virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD); /// Emit a code for initialization of threadprivate variable. It emits /// a call to runtime library which adds initial value to the newly created diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 299ee1460b3d..5baac8f0e3e2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -1096,7 +1096,8 @@ void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, llvm::PointerType *VarPtrTy = CGF.ConvertTypeForMem(VarTy)->getPointerTo(); llvm::Value *CastedVoidPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( VoidPtr, VarPtrTy, VD->getName() + "_on_stack"); - LValue VarAddr = CGF.MakeNaturalAlignAddrLValue(CastedVoidPtr, VarTy); + LValue VarAddr = + CGF.MakeNaturalAlignPointeeRawAddrLValue(CastedVoidPtr, VarTy); Rec.second.PrivateAddr = VarAddr.getAddress(CGF); Rec.second.GlobalizedVal = VoidPtr; @@ -1206,8 +1207,8 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, bool IsBareKernel = D.getSingleClause(); - Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, - /*Name=*/".zero.addr"); + RawAddress ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, + /*Name=*/".zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddr); llvm::SmallVector OutlinedFnArgs; // We don't emit any thread id function call in bare kernel, but because the @@ -1215,7 +1216,7 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, if (IsBareKernel) OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); else - OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); + OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); @@ -1289,7 +1290,7 @@ void CGOpenMPRuntimeGPU::emitParallelCall(CodeGenFunction &CGF, llvm::ConstantInt::get(CGF.Int32Ty, -1), FnPtr, ID, - Bld.CreateBitOrPointerCast(CapturedVarsAddrs.getPointer(), + Bld.CreateBitOrPointerCast(CapturedVarsAddrs.emitRawPointer(CGF), CGF.VoidPtrPtrTy), llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())}; CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -1503,17 +1504,18 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, CGF.EmitBlock(PreCondBB); llvm::PHINode *PhiSrc = Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2); - PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB); + PhiSrc->addIncoming(Ptr.emitRawPointer(CGF), CurrentBB); llvm::PHINode *PhiDest = Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2); - PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB); + PhiDest->addIncoming(ElemPtr.emitRawPointer(CGF), CurrentBB); Ptr = Address(PhiSrc, Ptr.getElementType(), Ptr.getAlignment()); ElemPtr = Address(PhiDest, ElemPtr.getElementType(), ElemPtr.getAlignment()); + llvm::Value *PtrEndRaw = PtrEnd.emitRawPointer(CGF); + llvm::Value *PtrRaw = Ptr.emitRawPointer(CGF); llvm::Value *PtrDiff = Bld.CreatePtrDiff( - CGF.Int8Ty, PtrEnd.getPointer(), - Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr.getPointer(), - CGF.VoidPtrTy)); + CGF.Int8Ty, PtrEndRaw, + Bld.CreatePointerBitCastOrAddrSpaceCast(PtrRaw, CGF.VoidPtrTy)); Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)), ThenBB, ExitBB); CGF.EmitBlock(ThenBB); @@ -1528,8 +1530,8 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, TBAAAccessInfo()); Address LocalPtr = Bld.CreateConstGEP(Ptr, 1); Address LocalElemPtr = Bld.CreateConstGEP(ElemPtr, 1); - PhiSrc->addIncoming(LocalPtr.getPointer(), ThenBB); - PhiDest->addIncoming(LocalElemPtr.getPointer(), ThenBB); + PhiSrc->addIncoming(LocalPtr.emitRawPointer(CGF), ThenBB); + PhiDest->addIncoming(LocalElemPtr.emitRawPointer(CGF), ThenBB); CGF.EmitBranch(PreCondBB); CGF.EmitBlock(ExitBB); } else { @@ -1676,10 +1678,10 @@ static void emitReductionListCopy( // scope and that of functions it invokes (i.e., reduce_function). // RemoteReduceData[i] = (void*)&RemoteElem if (UpdateDestListPtr) { - CGF.EmitStoreOfScalar(Bld.CreatePointerBitCastOrAddrSpaceCast( - DestElementAddr.getPointer(), CGF.VoidPtrTy), - DestElementPtrAddr, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar( + Bld.CreatePointerBitCastOrAddrSpaceCast( + DestElementAddr.emitRawPointer(CGF), CGF.VoidPtrTy), + DestElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy); } ++Idx; @@ -1830,7 +1832,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, // elemptr = ((CopyType*)(elemptrptr)) + I Address ElemPtr(ElemPtrPtr, CopyType, Align); if (NumIters > 1) - ElemPtr = Bld.CreateGEP(ElemPtr, Cnt); + ElemPtr = Bld.CreateGEP(CGF, ElemPtr, Cnt); // Get pointer to location in transfer medium. // MediumPtr = &medium[warp_id] @@ -1894,7 +1896,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, Loc); Address TargetElemPtr(TargetElemPtrVal, CopyType, Align); if (NumIters > 1) - TargetElemPtr = Bld.CreateGEP(TargetElemPtr, Cnt); + TargetElemPtr = Bld.CreateGEP(CGF, TargetElemPtr, Cnt); // *TargetElemPtr = SrcMediumVal; llvm::Value *SrcMediumValue = @@ -2105,9 +2107,9 @@ static llvm::Function *emitShuffleAndReduceFunction( CGF.EmitBlock(ThenBB); // reduce_function(LocalReduceList, RemoteReduceList) llvm::Value *LocalReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - LocalReduceList.getPointer(), CGF.VoidPtrTy); + LocalReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *RemoteReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - RemoteReduceList.getPointer(), CGF.VoidPtrTy); + RemoteReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); CGM.getOpenMPRuntime().emitOutlinedFunctionCall( CGF, Loc, ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr}); Bld.CreateBr(MergeBB); @@ -2218,9 +2220,9 @@ static llvm::Value *emitListToGlobalCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2304,7 +2306,7 @@ static llvm::Value *emitListToGlobalReduceFunction( // 1. Build a list of reduction variables. // void *RedList[] = {[0], ..., [-1]}; - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); auto IPriv = Privates.begin(); llvm::Value *Idxs[] = {CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(&IdxArg), @@ -2319,10 +2321,10 @@ static llvm::Value *emitListToGlobalReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2425,9 +2427,9 @@ static llvm::Value *emitGlobalToListCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2526,10 +2528,10 @@ static llvm::Value *emitGlobalToListReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2545,7 +2547,7 @@ static llvm::Value *emitGlobalToListReduceFunction( } // Call reduce_function(ReduceList, GlobalReduceList) - llvm::Value *GlobalReduceList = ReductionList.getPointer(); + llvm::Value *GlobalReduceList = ReductionList.emitRawPointer(CGF); Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg); llvm::Value *ReducedPtr = CGF.EmitLoadOfScalar( AddrReduceListArg, /*Volatile=*/false, C.VoidPtrTy, Loc); @@ -2876,7 +2878,7 @@ void CGOpenMPRuntimeGPU::emitReduction( } llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - ReductionList.getPointer(), CGF.VoidPtrTy); + ReductionList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Function *ReductionFn = emitReductionFunction( CGF.CurFn->getName(), Loc, CGF.ConvertTypeForMem(ReductionArrayTy), Privates, LHSExprs, RHSExprs, ReductionOps); @@ -3106,15 +3108,15 @@ llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper( // Get the array of arguments. SmallVector Args; - Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer()); - Args.emplace_back(ZeroAddr.getPointer()); + Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).emitRawPointer(CGF)); + Args.emplace_back(ZeroAddr.emitRawPointer(CGF)); CGBuilderTy &Bld = CGF.Builder; auto CI = CS.capture_begin(); // Use global memory for data sharing. // Handle passing of global args to workers. - Address GlobalArgs = + RawAddress GlobalArgs = CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args"); llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer(); llvm::Value *DataSharingArgs[] = {GlobalArgsPtr}; @@ -3400,7 +3402,7 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas( VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType().getCanonicalType()) .getAddress(CGF); - CGF.EmitStoreOfScalar(VDAddr.getPointer(), VarLVal); + CGF.EmitStoreOfScalar(VDAddr.emitRawPointer(CGF), VarLVal); } } } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index cb5a004e4f4a..576fe2f7a2d4 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2294,7 +2294,7 @@ std::pair CodeGenFunction::EmitAsmInputLValue( Address Addr = InputValue.getAddress(*this); ConstraintStr += '*'; - return {Addr.getPointer(), Addr.getElementType()}; + return {InputValue.getPointer(*this), Addr.getElementType()}; } std::pair @@ -2701,7 +2701,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { ArgTypes.push_back(DestAddr.getType()); ArgElemTypes.push_back(DestAddr.getElementType()); - Args.push_back(DestAddr.getPointer()); + Args.push_back(DestAddr.emitRawPointer(*this)); Constraints += "=*"; Constraints += OutputConstraint; ReadOnly = ReadNone = false; @@ -3076,8 +3076,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr)); // Initialize variable-length arrays. - LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), - Ctx.getTagDeclType(RD)); + LValue Base = MakeNaturalAlignRawAddrLValue( + CapturedStmtInfo->getContextValue(), Ctx.getTagDeclType(RD)); for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType()) { auto *ExprArg = diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f37ac549d10a..e6d504bcdeca 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -350,7 +350,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); llvm::Value *SrcAddrVal = EmitScalarConversion( - DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), + DstAddr.emitRawPointer(*this), + Ctx.getPointerType(Ctx.getUIntPtrType()), Ctx.getPointerType(CurField->getType()), CurCap->getLocation()); LValue SrcLV = MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); @@ -364,7 +365,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( CapturedVars.push_back(CV); } else { assert(CurCap->capturesVariable() && "Expected capture by reference."); - CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer()); + CapturedVars.push_back( + EmitLValue(*I).getAddress(*this).emitRawPointer(*this)); } } } @@ -375,8 +377,9 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, ASTContext &Ctx = CGF.getContext(); llvm::Value *CastedPtr = CGF.EmitScalarConversion( - AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(), + AddrLV.getAddress(CGF).emitRawPointer(CGF), Ctx.getUIntPtrType(), Ctx.getPointerType(DstType), Loc); + // FIXME: should the pointee type (DstType) be passed? Address TmpAddr = CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress(CGF); return TmpAddr; @@ -702,8 +705,8 @@ void CodeGenFunction::EmitOMPAggregateAssign( llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); SrcAddr = SrcAddr.withElementType(DestAddr.getElementType()); - llvm::Value *SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + llvm::Value *SrcBegin = SrcAddr.emitRawPointer(*this); + llvm::Value *DestBegin = DestAddr.emitRawPointer(*this); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = Builder.CreateInBoundsGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -1007,10 +1010,10 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { CopyBegin = createBasicBlock("copyin.not.master"); CopyEnd = createBasicBlock("copyin.not.master.end"); // TODO: Avoid ptrtoint conversion. - auto *MasterAddrInt = - Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy); - auto *PrivateAddrInt = - Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy); + auto *MasterAddrInt = Builder.CreatePtrToInt( + MasterAddr.emitRawPointer(*this), CGM.IntPtrTy); + auto *PrivateAddrInt = Builder.CreatePtrToInt( + PrivateAddr.emitRawPointer(*this), CGM.IntPtrTy); Builder.CreateCondBr( Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin, CopyEnd); @@ -1666,7 +1669,7 @@ Address CodeGenFunction::OMPBuilderCBHelpers::getAddrOfThreadPrivate( llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Data = - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy); + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy); llvm::ConstantInt *Size = CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)); std::string Suffix = getNameWithSeparators({"cache", ""}); llvm::Twine CacheName = Twine(CGM.getMangledName(VD)).concat(Suffix); @@ -2045,7 +2048,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { ->getParam(0) ->getType() .getNonReferenceType(); - Address CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); + RawAddress CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()}); llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count"); @@ -2061,7 +2064,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { LValue LCVal = EmitLValue(LoopVarRef); Address LoopVarAddress = LCVal.getAddress(*this); emitCapturedStmtCall(*this, LoopVarClosure, - {LoopVarAddress.getPointer(), IndVar}); + {LoopVarAddress.emitRawPointer(*this), IndVar}); RunCleanupsScope BodyScope(*this); EmitStmt(BodyStmt); @@ -4795,7 +4798,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.PrivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); CallArgs.push_back(PrivatePtr.getPointer()); @@ -4803,7 +4806,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4813,7 +4816,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.LastprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".lastpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4826,7 +4829,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( Ty = CGF.getContext().getPointerType(Ty); if (isAllocatableDecl(VD)) Ty = CGF.getContext().getPointerType(Ty); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(Ty), ".local.ptr.addr"); auto Result = UntiedLocalVars.insert( std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid()))); @@ -4859,7 +4862,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( if (auto *DI = CGF.getDebugInfo()) if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo()) (void)DI->EmitDeclareOfAutoVariable( - Pair.first, Pair.second.getPointer(), CGF.Builder, + Pair.first, Pair.second.getBasePointer(), CGF.Builder, /*UsePointerValue*/ true); } // Adjust mapping for internal locals by mapping actual memory instead of @@ -4912,14 +4915,14 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -4970,7 +4973,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5089,7 +5092,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( // If there is no user-defined mapper, the mapper array will be nullptr. In // this case, we don't need to privatize it. if (!isa_and_nonnull( - InputInfo.MappersArray.getPointer())) { + InputInfo.MappersArray.emitRawPointer(*this))) { MVD = createImplicitFirstprivateForType( getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc()); TargetScope.addPrivate(MVD, InputInfo.MappersArray); @@ -5115,7 +5118,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast(cast(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -5194,14 +5197,14 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -5247,7 +5250,7 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5394,7 +5397,7 @@ void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) { Dependencies.DepExprs.append(DC->varlist_begin(), DC->varlist_end()); Address DepAddr = CGM.getOpenMPRuntime().emitDepobjDependClause( *this, Dependencies, DC->getBeginLoc()); - EmitStoreOfScalar(DepAddr.getPointer(), DOLVal); + EmitStoreOfScalar(DepAddr.emitRawPointer(*this), DOLVal); return; } if (const auto *DC = S.getSingleClause()) { @@ -6471,21 +6474,21 @@ static void emitOMPAtomicCompareExpr( D->getType()->hasSignedIntegerRepresentation()); llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{ - XAddr.getPointer(), XAddr.getElementType(), + XAddr.emitRawPointer(CGF), XAddr.getElementType(), X->getType()->hasSignedIntegerRepresentation(), X->getType().isVolatileQualified()}; llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal; if (V) { LValue LV = CGF.EmitLValue(V); Address Addr = LV.getAddress(CGF); - VOpVal = {Addr.getPointer(), Addr.getElementType(), + VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), V->getType()->hasSignedIntegerRepresentation(), V->getType().isVolatileQualified()}; } if (R) { LValue LV = CGF.EmitLValue(R); Address Addr = LV.getAddress(CGF); - ROpVal = {Addr.getPointer(), Addr.getElementType(), + ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), R->getType()->hasSignedIntegerRepresentation(), R->getType().isVolatileQualified()}; } @@ -7029,7 +7032,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) { std::tie(NumDependences, DependenciesArray) = CGM.getOpenMPRuntime().emitDependClause(*this, Data.Dependences, S.getBeginLoc()); - DependenceList = DependenciesArray.getPointer(); + DependenceList = DependenciesArray.emitRawPointer(*this); } Data.HasNowaitClause = S.hasClausesOfKind(); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 8dee3f74b44b..862369ae009f 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -201,14 +201,13 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, // Find the first store of "this", which will be to the alloca associated // with "this". - Address ThisPtr = - Address(&*AI, ConvertTypeForMem(MD->getFunctionObjectParameterType()), - CGM.getClassPointerAlignment(MD->getParent())); + Address ThisPtr = makeNaturalAddressForPointer( + &*AI, MD->getFunctionObjectParameterType(), + CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = llvm::find_if(*EntryBB, [&](llvm::Instruction &I) { - return isa(I) && - I.getOperand(0) == ThisPtr.getPointer(); + return isa(I) && I.getOperand(0) == &*AI; }); assert(ThisStore != EntryBB->end() && "Store of this should be in entry block?"); diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index 1e6f67250583..cc9ad10ae596 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -14,12 +14,13 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H +#include "Address.h" +#include "CodeGenTBAA.h" +#include "EHScopeStack.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" -#include "llvm/IR/Value.h" #include "llvm/IR/Type.h" -#include "Address.h" -#include "CodeGenTBAA.h" +#include "llvm/IR/Value.h" namespace llvm { class Constant; @@ -28,57 +29,64 @@ namespace llvm { namespace clang { namespace CodeGen { - class AggValueSlot; - class CodeGenFunction; - struct CGBitFieldInfo; +class AggValueSlot; +class CGBuilderTy; +class CodeGenFunction; +struct CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an /// expression that is evaluated. It can be one of three things: either a /// simple LLVM SSA value, a pair of SSA values for complex numbers, or the /// address of an aggregate value in memory. class RValue { - enum Flavor { Scalar, Complex, Aggregate }; + friend struct DominatingValue; - // The shift to make to an aggregate's alignment to make it look - // like a pointer. - enum { AggAlignShift = 4 }; + enum FlavorEnum { Scalar, Complex, Aggregate }; - // Stores first value and flavor. - llvm::PointerIntPair V1; - // Stores second value and volatility. - llvm::PointerIntPair V2; - // Stores element type for aggregate values. - llvm::Type *ElementType; + union { + // Stores first and second value. + struct { + llvm::Value *first; + llvm::Value *second; + } Vals; + + // Stores aggregate address. + Address AggregateAddr; + }; + + unsigned IsVolatile : 1; + unsigned Flavor : 2; public: - bool isScalar() const { return V1.getInt() == Scalar; } - bool isComplex() const { return V1.getInt() == Complex; } - bool isAggregate() const { return V1.getInt() == Aggregate; } + RValue() : Vals{nullptr, nullptr}, Flavor(Scalar) {} + + bool isScalar() const { return Flavor == Scalar; } + bool isComplex() const { return Flavor == Complex; } + bool isAggregate() const { return Flavor == Aggregate; } - bool isVolatileQualified() const { return V2.getInt(); } + bool isVolatileQualified() const { return IsVolatile; } /// getScalarVal() - Return the Value* of this scalar value. llvm::Value *getScalarVal() const { assert(isScalar() && "Not a scalar!"); - return V1.getPointer(); + return Vals.first; } /// getComplexVal - Return the real/imag components of this complex value. /// std::pair getComplexVal() const { - return std::make_pair(V1.getPointer(), V2.getPointer()); + return std::make_pair(Vals.first, Vals.second); } /// getAggregateAddr() - Return the Value* of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); - auto align = reinterpret_cast(V2.getPointer()) >> AggAlignShift; - return Address( - V1.getPointer(), ElementType, CharUnits::fromQuantity(align)); + return AggregateAddr; } - llvm::Value *getAggregatePointer() const { - assert(isAggregate() && "Not an aggregate!"); - return V1.getPointer(); + + llvm::Value *getAggregatePointer(QualType PointeeType, + CodeGenFunction &CGF) const { + return getAggregateAddress().getBasePointer(); } static RValue getIgnored() { @@ -88,17 +96,19 @@ public: static RValue get(llvm::Value *V) { RValue ER; - ER.V1.setPointer(V); - ER.V1.setInt(Scalar); - ER.V2.setInt(false); + ER.Vals.first = V; + ER.Flavor = Scalar; + ER.IsVolatile = false; return ER; } + static RValue get(Address Addr, CodeGenFunction &CGF) { + return RValue::get(Addr.emitRawPointer(CGF)); + } static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { RValue ER; - ER.V1.setPointer(V1); - ER.V2.setPointer(V2); - ER.V1.setInt(Complex); - ER.V2.setInt(false); + ER.Vals = {V1, V2}; + ER.Flavor = Complex; + ER.IsVolatile = false; return ER; } static RValue getComplex(const std::pair &C) { @@ -107,15 +117,15 @@ public: // FIXME: Aggregate rvalues need to retain information about whether they are // volatile or not. Remove default to find all places that probably get this // wrong. + + /// Convert an Address to an RValue. If the Address is not + /// signed, create an RValue using the unsigned address. Otherwise, resign the + /// address using the provided type. static RValue getAggregate(Address addr, bool isVolatile = false) { RValue ER; - ER.V1.setPointer(addr.getPointer()); - ER.V1.setInt(Aggregate); - ER.ElementType = addr.getElementType(); - - auto align = static_cast(addr.getAlignment().getQuantity()); - ER.V2.setPointer(reinterpret_cast(align << AggAlignShift)); - ER.V2.setInt(isVolatile); + ER.AggregateAddr = addr; + ER.Flavor = Aggregate; + ER.IsVolatile = isVolatile; return ER; } }; @@ -178,8 +188,10 @@ class LValue { MatrixElt // This is a matrix element, use getVector* } LVType; - llvm::Value *V; - llvm::Type *ElementType; + union { + Address Addr = Address::invalid(); + llvm::Value *V; + }; union { // Index into a vector subscript: V[i] @@ -197,10 +209,6 @@ class LValue { // 'const' is unused here Qualifiers Quals; - // The alignment to use when accessing this lvalue. (For vector elements, - // this is the alignment of the whole vector.) - unsigned Alignment; - // objective-c's ivar bool Ivar:1; @@ -234,23 +242,19 @@ class LValue { Expr *BaseIvarExp; private: - void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, + void Initialize(QualType Type, Qualifiers Quals, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - assert((!Alignment.isZero() || Type->isIncompleteType()) && - "initializing l-value with zero alignment!"); - if (isGlobalReg()) - assert(ElementType == nullptr && "Global reg does not store elem type"); - else - assert(ElementType != nullptr && "Must have elem type"); - this->Type = Type; this->Quals = Quals; const unsigned MaxAlign = 1U << 31; - this->Alignment = Alignment.getQuantity() <= MaxAlign - ? Alignment.getQuantity() - : MaxAlign; - assert(this->Alignment == Alignment.getQuantity() && - "Alignment exceeds allowed max!"); + CharUnits Alignment = Addr.getAlignment(); + assert((isGlobalReg() || !Alignment.isZero() || Type->isIncompleteType()) && + "initializing l-value with zero alignment!"); + if (Alignment.getQuantity() > MaxAlign) { + assert(false && "Alignment exceeds allowed max!"); + Alignment = CharUnits::fromQuantity(MaxAlign); + } + this->Addr = Addr; this->BaseInfo = BaseInfo; this->TBAAInfo = TBAAInfo; @@ -259,9 +263,20 @@ private: this->ImpreciseLifetime = false; this->Nontemporal = false; this->ThreadLocalRef = false; + this->IsKnownNonNull = false; this->BaseIvarExp = nullptr; } + void initializeSimpleLValue(Address Addr, QualType Type, + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, + ASTContext &Context) { + Qualifiers QS = Type.getQualifiers(); + QS.setObjCGCAttr(Context.getObjCGCAttrKind(Type)); + LVType = Simple; + Initialize(Type, QS, Addr, BaseInfo, TBAAInfo); + assert(Addr.getBasePointer()->getType()->isPointerTy()); + } + public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } @@ -328,8 +343,8 @@ public: LangAS getAddressSpace() const { return Quals.getAddressSpace(); } - CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } - void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } + CharUnits getAlignment() const { return Addr.getAlignment(); } + void setAlignment(CharUnits A) { Addr.setAlignment(A); } LValueBaseInfo getBaseInfo() const { return BaseInfo; } void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } @@ -345,28 +360,32 @@ public: // simple lvalue llvm::Value *getPointer(CodeGenFunction &CGF) const { assert(isSimple()); - return V; + return Addr.getBasePointer(); } - Address getAddress(CodeGenFunction &CGF) const { - return Address(getPointer(CGF), ElementType, getAlignment(), - isKnownNonNull()); - } - void setAddress(Address address) { + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { assert(isSimple()); - V = address.getPointer(); - ElementType = address.getElementType(); - Alignment = address.getAlignment().getQuantity(); - IsKnownNonNull = address.isKnownNonNull(); + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } + Address getAddress(CodeGenFunction &CGF) const { + // FIXME: remove parameter. + return Addr; + } + + void setAddress(Address address) { Addr = address; } + // vector elt lvalue Address getVectorAddress() const { - return Address(getVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isVectorElt()); + return Addr; + } + llvm::Value *getRawVectorPointer(CodeGenFunction &CGF) const { + assert(isVectorElt()); + return Addr.emitRawPointer(CGF); } llvm::Value *getVectorPointer() const { assert(isVectorElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getVectorIdx() const { assert(isVectorElt()); @@ -374,12 +393,12 @@ public: } Address getMatrixAddress() const { - return Address(getMatrixPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isMatrixElt()); + return Addr; } llvm::Value *getMatrixPointer() const { assert(isMatrixElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getMatrixIdx() const { assert(isMatrixElt()); @@ -388,12 +407,12 @@ public: // extended vector elements. Address getExtVectorAddress() const { - return Address(getExtVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isExtVectorElt()); + return Addr; } - llvm::Value *getExtVectorPointer() const { + llvm::Value *getRawExtVectorPointer(CodeGenFunction &CGF) const { assert(isExtVectorElt()); - return V; + return Addr.emitRawPointer(CGF); } llvm::Constant *getExtVectorElts() const { assert(isExtVectorElt()); @@ -402,10 +421,14 @@ public: // bitfield lvalue Address getBitFieldAddress() const { - return Address(getBitFieldPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isBitField()); + return Addr; + } + llvm::Value *getRawBitFieldPointer(CodeGenFunction &CGF) const { + assert(isBitField()); + return Addr.emitRawPointer(CGF); } - llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; } + const CGBitFieldInfo &getBitFieldInfo() const { assert(isBitField()); return *BitFieldInfo; @@ -414,18 +437,13 @@ public: // global register lvalue llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } - static LValue MakeAddr(Address address, QualType type, ASTContext &Context, + static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - Qualifiers qs = type.getQualifiers(); - qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); - LValue R; R.LVType = Simple; - assert(address.getPointer()->getType()->isPointerTy()); - R.V = address.getPointer(); - R.ElementType = address.getElementType(); - R.IsKnownNonNull = address.isKnownNonNull(); - R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); + R.initializeSimpleLValue(Addr, type, BaseInfo, TBAAInfo, Context); + R.Addr = Addr; + assert(Addr.getType()->isPointerTy()); return R; } @@ -434,26 +452,18 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = VectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), vecAddress, BaseInfo, TBAAInfo); return R; } - static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, + static LValue MakeExtVectorElt(Address Addr, llvm::Constant *Elts, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = ExtVectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorElts = Elts; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -468,12 +478,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = BitField; - R.V = Addr.getPointer(); - R.ElementType = Addr.getElementType(); R.BitFieldInfo = &Info; - R.IsKnownNonNull = Addr.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, - TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -481,11 +487,9 @@ public: QualType type) { LValue R; R.LVType = GlobalReg; - R.V = V; - R.ElementType = nullptr; - R.IsKnownNonNull = true; - R.Initialize(type, type.getQualifiers(), alignment, + R.Initialize(type, type.getQualifiers(), Address::invalid(), LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); + R.V = V; return R; } @@ -494,12 +498,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = MatrixElt; - R.V = matAddress.getPointer(); - R.ElementType = matAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = matAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), matAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), matAddress, BaseInfo, TBAAInfo); return R; } @@ -643,17 +643,17 @@ public: return NeedsGCBarriers_t(ObjCGCFlag); } - llvm::Value *getPointer() const { - return Addr.getPointer(); + llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; + + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } Address getAddress() const { return Addr; } - bool isIgnored() const { - return !Addr.isValid(); - } + bool isIgnored() const { return !Addr.isValid(); } CharUnits getAlignment() const { return Addr.getAlignment(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index f2ebaf767452..44103884940f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -193,26 +193,35 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() { CGF.Builder.setDefaultConstrainedRounding(OldRounding); } -LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { +static LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, + bool ForPointeeType, + CodeGenFunction &CGF) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - CharUnits Alignment = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo); - Address Addr(V, ConvertTypeForMem(T), Alignment); - return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo); + CharUnits Alignment = + CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType); + Address Addr = Address(V, CGF.ConvertTypeForMem(T), Alignment); + return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); +} + +LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); } -/// Given a value of type T* that may not be to a complete object, -/// construct an l-value with the natural pointee alignment of T. LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - CharUnits Align = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, - /* forPointeeType= */ true); - Address Addr(V, ConvertTypeForMem(T), Align); - return MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); +} + +LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); } +LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); +} llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { return CGM.getTypes().ConvertTypeForMem(T); @@ -525,7 +534,8 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { ReturnBlock.getBlock()->eraseFromParent(); } if (ReturnValue.isValid()) { - auto *RetAlloca = dyn_cast(ReturnValue.getPointer()); + auto *RetAlloca = + dyn_cast(ReturnValue.emitRawPointer(*this)); if (RetAlloca && RetAlloca->use_empty()) { RetAlloca->eraseFromParent(); ReturnValue = Address::invalid(); @@ -1122,13 +1132,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, auto AI = CurFn->arg_begin(); if (CurFnInfo->getReturnInfo().isSRetAfterThis()) ++AI; - ReturnValue = - Address(&*AI, ConvertType(RetTy), - CurFnInfo->getReturnInfo().getIndirectAlign(), KnownNonNull); + ReturnValue = makeNaturalAddressForPointer( + &*AI, RetTy, CurFnInfo->getReturnInfo().getIndirectAlign(), false, + nullptr, nullptr, KnownNonNull); if (!CurFnInfo->getReturnInfo().getIndirectByVal()) { - ReturnValuePointer = CreateDefaultAlignTempAlloca( - ReturnValue.getPointer()->getType(), "result.ptr"); - Builder.CreateStore(ReturnValue.getPointer(), ReturnValuePointer); + ReturnValuePointer = + CreateDefaultAlignTempAlloca(ReturnValue.getType(), "result.ptr"); + Builder.CreateStore(ReturnValue.emitRawPointer(*this), + ReturnValuePointer); } } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { @@ -1189,8 +1200,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // or contains the address of the enclosing object). LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - // If the enclosing object was captured by value, just use its address. - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + // If the enclosing object was captured by value, just use its + // address. Sign this pointer. + CXXThisValue = ThisFieldLValue.getPointer(*this); } else { // Load the lvalue pointed to by the field, since '*this' was captured // by reference. @@ -2012,8 +2024,9 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); Address begin = dest.withElementType(CGF.Int8Ty); - llvm::Value *end = Builder.CreateInBoundsGEP( - begin.getElementType(), begin.getPointer(), sizeInChars, "vla.end"); + llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(), + begin.emitRawPointer(CGF), + sizeInChars, "vla.end"); llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock(); llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop"); @@ -2024,7 +2037,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, CGF.EmitBlock(loopBB); llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur"); - cur->addIncoming(begin.getPointer(), originBB); + cur->addIncoming(begin.emitRawPointer(CGF), originBB); CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize); @@ -2217,10 +2230,10 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, addr = addr.withElementType(baseType); } else { // Create the actual GEP. - addr = Address(Builder.CreateInBoundsGEP( - addr.getElementType(), addr.getPointer(), gepIndices, "array.begin"), - ConvertTypeForMem(eltType), - addr.getAlignment()); + addr = Address(Builder.CreateInBoundsGEP(addr.getElementType(), + addr.emitRawPointer(*this), + gepIndices, "array.begin"), + ConvertTypeForMem(eltType), addr.getAlignment()); } baseType = eltType; @@ -2561,7 +2574,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) { Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, Address Addr) { assert(D->hasAttr() && "no annotate attribute"); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.emitRawPointer(*this); llvm::Type *VTy = V->getType(); auto *PTy = dyn_cast(VTy); unsigned AS = PTy ? PTy->getAddressSpace() : 0; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e8f8aa601ed0..8dd6da5f85f1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -151,6 +151,9 @@ struct DominatingLLVMValue { /// Answer whether the given value needs extra work to be saved. static bool needsSaving(llvm::Value *value) { + if (!value) + return false; + // If it's not an instruction, we don't need to save. if (!isa(value)) return false; @@ -177,21 +180,28 @@ template <> struct DominatingValue
{ typedef Address type; struct saved_type { - DominatingLLVMValue::saved_type SavedValue; + DominatingLLVMValue::saved_type BasePtr; llvm::Type *ElementType; CharUnits Alignment; + DominatingLLVMValue::saved_type Offset; + llvm::PointerType *EffectiveType; }; static bool needsSaving(type value) { - return DominatingLLVMValue::needsSaving(value.getPointer()); + if (DominatingLLVMValue::needsSaving(value.getBasePointer()) || + DominatingLLVMValue::needsSaving(value.getOffset())) + return true; + return false; } static saved_type save(CodeGenFunction &CGF, type value) { - return { DominatingLLVMValue::save(CGF, value.getPointer()), - value.getElementType(), value.getAlignment() }; + return {DominatingLLVMValue::save(CGF, value.getBasePointer()), + value.getElementType(), value.getAlignment(), + DominatingLLVMValue::save(CGF, value.getOffset()), value.getType()}; } static type restore(CodeGenFunction &CGF, saved_type value) { - return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), - value.ElementType, value.Alignment); + return Address(DominatingLLVMValue::restore(CGF, value.BasePtr), + value.ElementType, value.Alignment, + DominatingLLVMValue::restore(CGF, value.Offset)); } }; @@ -201,14 +211,26 @@ template <> struct DominatingValue { class saved_type { enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, AggregateAddress, ComplexAddress }; - - llvm::Value *Value; - llvm::Type *ElementType; + union { + struct { + DominatingLLVMValue::saved_type first, second; + } Vals; + DominatingValue
::saved_type AggregateAddr; + }; LLVM_PREFERRED_TYPE(Kind) unsigned K : 3; - unsigned Align : 29; - saved_type(llvm::Value *v, llvm::Type *e, Kind k, unsigned a = 0) - : Value(v), ElementType(e), K(k), Align(a) {} + unsigned IsVolatile : 1; + + saved_type(DominatingLLVMValue::saved_type Val1, unsigned K) + : Vals{Val1, DominatingLLVMValue::saved_type()}, K(K) {} + + saved_type(DominatingLLVMValue::saved_type Val1, + DominatingLLVMValue::saved_type Val2) + : Vals{Val1, Val2}, K(ComplexAddress) {} + + saved_type(DominatingValue
::saved_type AggregateAddr, + bool IsVolatile, unsigned K) + : AggregateAddr(AggregateAddr), K(K) {} public: static bool needsSaving(RValue value); @@ -659,7 +681,7 @@ public: llvm::Value *Size; public: - CallLifetimeEnd(Address addr, llvm::Value *size) + CallLifetimeEnd(RawAddress addr, llvm::Value *size) : Addr(addr.getPointer()), Size(size) {} void Emit(CodeGenFunction &CGF, Flags flags) override { @@ -684,7 +706,7 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest = Address::invalid(); + RawAddress NormalCleanupDest = RawAddress::invalid(); unsigned NextCleanupDestIndex = 1; @@ -819,10 +841,10 @@ public: template void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) { if (!isInConditionalBranch()) - return pushCleanupAfterFullExprWithActiveFlag(Kind, Address::invalid(), - A...); + return pushCleanupAfterFullExprWithActiveFlag( + Kind, RawAddress::invalid(), A...); - Address ActiveFlag = createCleanupActiveFlag(); + RawAddress ActiveFlag = createCleanupActiveFlag(); assert(!DominatingValue
::needsSaving(ActiveFlag) && "cleanup active flag should never need saving"); @@ -835,7 +857,7 @@ public: template void pushCleanupAfterFullExprWithActiveFlag(CleanupKind Kind, - Address ActiveFlag, As... A) { + RawAddress ActiveFlag, As... A) { LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind, ActiveFlag.isValid()}; @@ -850,7 +872,7 @@ public: new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer + sizeof(Header)) T(A...); if (Header.IsConditional) - new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag); + new (Buffer + sizeof(Header) + sizeof(T)) RawAddress(ActiveFlag); } /// Set up the last cleanup that was pushed as a conditional @@ -859,8 +881,8 @@ public: initFullExprCleanupWithFlag(createCleanupActiveFlag()); } - void initFullExprCleanupWithFlag(Address ActiveFlag); - Address createCleanupActiveFlag(); + void initFullExprCleanupWithFlag(RawAddress ActiveFlag); + RawAddress createCleanupActiveFlag(); /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the @@ -1048,7 +1070,7 @@ public: QualType VarTy = LocalVD->getType(); if (VarTy->isReferenceType()) { Address Temp = CGF.CreateMemTemp(VarTy); - CGF.Builder.CreateStore(TempAddr.getPointer(), Temp); + CGF.Builder.CreateStore(TempAddr.emitRawPointer(CGF), Temp); TempAddr = Temp; } SavedTempAddresses.try_emplace(LocalVD, TempAddr); @@ -1243,10 +1265,12 @@ public: /// one branch or the other of a conditional expression. bool isInConditionalBranch() const { return OutermostConditional != nullptr; } - void setBeforeOutermostConditional(llvm::Value *value, Address addr) { + void setBeforeOutermostConditional(llvm::Value *value, Address addr, + CodeGenFunction &CGF) { assert(isInConditionalBranch()); llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back()); + auto store = + new llvm::StoreInst(value, addr.emitRawPointer(CGF), &block->back()); store->setAlignment(addr.getAlignment().getAsAlign()); } @@ -1601,7 +1625,7 @@ public: /// If \p StepV is null, the default increment is 1. void maybeUpdateMCDCTestVectorBitmap(const Expr *E) { if (isMCDCCoverageEnabled() && isBinaryLogicalOp(E)) { - PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr); + PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr, *this); PGO.setCurrentStmt(E); } } @@ -1609,7 +1633,7 @@ public: /// Update the MCDC temp value with the condition's evaluated result. void maybeUpdateMCDCCondBitmap(const Expr *E, llvm::Value *Val) { if (isMCDCCoverageEnabled()) { - PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val); + PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val, *this); PGO.setCurrentStmt(E); } } @@ -1704,7 +1728,7 @@ public: : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue), OldCXXThisAlignment(CGF.CXXThisAlignment), SourceLocScope(E, CGF.CurSourceLocExprScope) { - CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer(); + CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getBasePointer(); CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment(); } ~CXXDefaultInitExprScope() { @@ -2090,7 +2114,7 @@ public: llvm::Value *getExceptionFromSlot(); llvm::Value *getSelectorFromSlot(); - Address getNormalCleanupDestSlot(); + RawAddress getNormalCleanupDestSlot(); llvm::BasicBlock *getUnreachableBlock() { if (!UnreachableBlock) { @@ -2579,10 +2603,40 @@ public: // Helpers //===--------------------------------------------------------------------===// + Address mergeAddressesInConditionalExpr(Address LHS, Address RHS, + llvm::BasicBlock *LHSBlock, + llvm::BasicBlock *RHSBlock, + llvm::BasicBlock *MergeBlock, + QualType MergedType) { + Builder.SetInsertPoint(MergeBlock); + llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); + PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); + PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); + LHS.replaceBasePointer(PtrPhi); + LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); + return LHS; + } + + /// Construct an address with the natural alignment of T. If a pointer to T + /// is expected to be signed, the pointer passed to this function must have + /// been signed, and the returned Address will have the pointer authentication + /// information needed to authenticate the signed pointer. + Address makeNaturalAddressForPointer( + llvm::Value *Ptr, QualType T, CharUnits Alignment = CharUnits::Zero(), + bool ForPointeeType = false, LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) { + if (Alignment.isZero()) + Alignment = + CGM.getNaturalTypeAlignment(T, BaseInfo, TBAAInfo, ForPointeeType); + return Address(Ptr, ConvertTypeForMem(T), Alignment, nullptr, + IsKnownNonNull); + } + LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source = AlignmentSource::Type) { - return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(T)); + return MakeAddrLValue(Addr, T, LValueBaseInfo(Source), + CGM.getTBAAAccessInfo(T)); } LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo, @@ -2592,6 +2646,14 @@ public: LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source = AlignmentSource::Type) { + return MakeAddrLValue(makeNaturalAddressForPointer(V, T, Alignment), T, + LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); + } + + /// Same as MakeAddrLValue above except that the pointer is known to be + /// unsigned. + LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, + AlignmentSource Source = AlignmentSource::Type) { Address Addr(V, ConvertTypeForMem(T), Alignment); return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); @@ -2604,9 +2666,18 @@ public: TBAAAccessInfo()); } + /// Given a value of type T* that may not be to a complete object, construct + /// an l-value with the natural pointee alignment of T. LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); + LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); + /// Same as MakeNaturalAlignPointeeAddrLValue except that the pointer is known + /// to be unsigned. + LValue MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T); + + LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T); + Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo = nullptr, TBAAAccessInfo *PointeeTBAAInfo = nullptr); @@ -2655,13 +2726,13 @@ public: /// more efficient if the caller knows that the address will not be exposed. llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr); - Address CreateTempAlloca(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr, - Address *Alloca = nullptr); - Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); + RawAddress CreateTempAlloca(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr, + RawAddress *Alloca = nullptr); + RawAddress CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr); /// CreateDefaultAlignedTempAlloca - This creates an alloca with the /// default ABI alignment of the given LLVM type. @@ -2673,8 +2744,8 @@ public: /// not hand this address off to arbitrary IRGen routines, and especially /// do not pass it as an argument to a function that might expect a /// properly ABI-aligned value. - Address CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name = "tmp"); + RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name = "tmp"); /// CreateIRTemp - Create a temporary IR object of the given type, with /// appropriate alignment. This routine should only be used when an temporary @@ -2684,32 +2755,31 @@ public: /// /// That is, this is exactly equivalent to CreateMemTemp, but calling /// ConvertType instead of ConvertTypeForMem. - Address CreateIRTemp(QualType T, const Twine &Name = "tmp"); + RawAddress CreateIRTemp(QualType T, const Twine &Name = "tmp"); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen and cast it to the default address space. Returns /// the original alloca instruction by \p Alloca if it is not nullptr. - Address CreateMemTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr); - Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp", - Address *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, CharUnits Align, + const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen without casting it to the default address space. - Address CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); - Address CreateMemTempWithoutCast(QualType T, CharUnits Align, - const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, CharUnits Align, + const Twine &Name = "tmp"); /// CreateAggTemp - Create a temporary memory object for the given /// aggregate type. AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr) { - return AggValueSlot::forAddr(CreateMemTemp(T, Name, Alloca), - T.getQualifiers(), - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); + RawAddress *Alloca = nullptr) { + return AggValueSlot::forAddr( + CreateMemTemp(T, Name, Alloca), T.getQualifiers(), + AggValueSlot::IsNotDestructed, AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap); } /// EvaluateExprAsBool - Perform the usual unary conversions on the specified @@ -3083,6 +3153,25 @@ public: /// calls to EmitTypeCheck can be skipped. bool sanitizePerformTypeCheck() const; + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, + QualType Type, SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, LV.emitRawPointer(*this), Type, LV.getAlignment(), + SkippedChecks, ArraySize); + } + + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, Address Addr, + QualType Type, CharUnits Alignment = CharUnits::Zero(), + SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, Addr.emitRawPointer(*this), Type, Alignment, + SkippedChecks, ArraySize); + } + /// Emit a check that \p V is the address of storage of the /// appropriate size and alignment for an object of type \p Type /// (or if ArraySize is provided, for an array of that bound). @@ -3183,17 +3272,17 @@ public: /// Address with original alloca instruction. Invalid if the variable was /// emitted as a global constant. - Address AllocaAddr; + RawAddress AllocaAddr; struct Invalid {}; AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()), - AllocaAddr(Address::invalid()) {} + AllocaAddr(RawAddress::invalid()) {} AutoVarEmission(const VarDecl &variable) : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr), IsEscapingByRef(false), IsConstantAggregate(false), - SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {} + SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {} bool wasEmittedAsGlobal() const { return !Addr.isValid(); } @@ -3216,7 +3305,7 @@ public: } /// Returns the address for the original alloca instruction. - Address getOriginalAllocatedAddress() const { return AllocaAddr; } + RawAddress getOriginalAllocatedAddress() const { return AllocaAddr; } /// Returns the address of the object within this declaration. /// Note that this does not chase the forwarding pointer for @@ -3246,23 +3335,32 @@ public: llvm::GlobalValue::LinkageTypes Linkage); class ParamValue { - llvm::Value *Value; - llvm::Type *ElementType; - unsigned Alignment; - ParamValue(llvm::Value *V, llvm::Type *T, unsigned A) - : Value(V), ElementType(T), Alignment(A) {} + union { + Address Addr; + llvm::Value *Value; + }; + + bool IsIndirect; + + ParamValue(llvm::Value *V) : Value(V), IsIndirect(false) {} + ParamValue(Address A) : Addr(A), IsIndirect(true) {} + public: static ParamValue forDirect(llvm::Value *value) { - return ParamValue(value, nullptr, 0); + return ParamValue(value); } static ParamValue forIndirect(Address addr) { assert(!addr.getAlignment().isZero()); - return ParamValue(addr.getPointer(), addr.getElementType(), - addr.getAlignment().getQuantity()); + return ParamValue(addr); } - bool isIndirect() const { return Alignment != 0; } - llvm::Value *getAnyValue() const { return Value; } + bool isIndirect() const { return IsIndirect; } + llvm::Value *getAnyValue() const { + if (!isIndirect()) + return Value; + assert(!Addr.hasOffset() && "unexpected offset"); + return Addr.getBasePointer(); + } llvm::Value *getDirectValue() const { assert(!isIndirect()); @@ -3271,8 +3369,7 @@ public: Address getIndirectAddress() const { assert(isIndirect()); - return Address(Value, ElementType, CharUnits::fromQuantity(Alignment), - KnownNonNull); + return Addr; } }; @@ -4182,6 +4279,9 @@ public: const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name = ""); + llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef
args, + const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef args, const Twine &name = ""); @@ -4208,6 +4308,12 @@ public: CXXDtorType Type, const CXXRecordDecl *RD); + llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { + return Addr.getBasePointer(); + } + + bool isPointerKnownNonNull(const Expr *E); + // Return the copy constructor name with the prefix "__copy_constructor_" // removed. static std::string getNonTrivialCopyConstructorStr(QualType QT, @@ -4780,6 +4886,11 @@ public: SourceLocation Loc, const Twine &Name = ""); + Address EmitCheckedInBoundsGEP(Address Addr, ArrayRef IdxList, + llvm::Type *elementType, bool SignedIndices, + bool IsSubtraction, SourceLocation Loc, + CharUnits Align, const Twine &Name = ""); + /// Specifies which type of sanitizer check to apply when handling a /// particular builtin. enum BuiltinCheckKind { @@ -4842,6 +4953,10 @@ public: void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, AbstractCallee AC, unsigned ParmNum); + void EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, AbstractCallee AC, + unsigned ParmNum); + /// EmitCallArg - Emit a single call argument. void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); @@ -5050,7 +5165,7 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); CGF.Builder.CreateStore(value, alloca); - return saved_type(alloca.getPointer(), true); + return saved_type(alloca.emitRawPointer(CGF), true); } inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e3ed5e90f2d3..00b3bfcaa0bc 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -7267,7 +7267,7 @@ void CodeGenFunction::EmitDeclMetadata() { for (auto &I : LocalDeclMap) { const Decl *D = I.first; - llvm::Value *Addr = I.second.getPointer(); + llvm::Value *Addr = I.second.emitRawPointer(*this); if (auto *Alloca = dyn_cast(Addr)) { llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); Alloca->setMetadata( diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 2619edfeb7dc..76704c4d7be4 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1239,7 +1239,8 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) { void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr) { + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1262,7 +1263,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, Builder.getInt64(FunctionHash), Builder.getInt32(RegionMCDCState->BitmapBytes), Builder.getInt32(MCDCTestVectorBitmapOffset), - MCDCCondBitmapAddr.getPointer()}; + MCDCCondBitmapAddr.emitRawPointer(CGF)}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args); } @@ -1283,7 +1284,8 @@ void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr, - llvm::Value *Val) { + llvm::Value *Val, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1312,7 +1314,7 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), Builder.getInt64(FunctionHash), Builder.getInt32(Branch.ID), - MCDCCondBitmapAddr.getPointer(), Val}; + MCDCCondBitmapAddr.emitRawPointer(CGF), Val}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update), Args); diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 036fbf6815a4..9d66ffad6f43 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -113,12 +113,14 @@ public: void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, llvm::Value *StepV); void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr); + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF); void emitMCDCParameters(CGBuilderTy &Builder); void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr); void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, llvm::Value *Val); + Address MCDCCondBitmapAddr, llvm::Value *Val, + CodeGenFunction &CGF); /// Return the region count for the counter at the given index. uint64_t getRegionCount(const Stmt *S) { diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index bdd53a192f82..fd71317572f0 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -307,10 +307,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase); - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -646,7 +642,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( // Apply the adjustment and cast back to the original struct type // for consistency. - llvm::Value *This = ThisAddr.getPointer(); + llvm::Value *This = ThisAddr.emitRawPointer(CGF); This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj); ThisPtrForCall = This; @@ -850,7 +846,7 @@ llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( CGBuilderTy &Builder = CGF.Builder; // Apply the offset, which we assume is non-null. - return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.getPointer(), MemPtr, + return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr, "memptr.offset"); } @@ -1245,7 +1241,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, CGF.getPointerAlign()); // Apply the offset. - llvm::Value *CompletePtr = Ptr.getPointer(); + llvm::Value *CompletePtr = Ptr.emitRawPointer(CGF); CompletePtr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset); @@ -1482,7 +1478,8 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastCall( computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity()); // Emit the call to __dynamic_cast. - llvm::Value *Args[] = {ThisAddr.getPointer(), SrcRTTI, DestRTTI, OffsetHint}; + llvm::Value *Args[] = {ThisAddr.emitRawPointer(CGF), SrcRTTI, DestRTTI, + OffsetHint}; llvm::Value *Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), Args); @@ -1571,7 +1568,7 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast( VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy)); llvm::Value *Success = CGF.Builder.CreateICmpEQ( VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl)); - llvm::Value *Result = ThisAddr.getPointer(); + llvm::Value *Result = ThisAddr.emitRawPointer(CGF); if (!Offset->isZero()) Result = CGF.Builder.CreateInBoundsGEP( CGF.CharTy, Result, @@ -1611,7 +1608,7 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top"); } // Finally, add the offset to the pointer. - return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.getPointer(), + return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.emitRawPointer(CGF), OffsetToTop); } @@ -1792,8 +1789,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, - nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, VTT, VTTTy, nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1952,11 +1949,6 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( CGF.getPointerAlign()); } -llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - return getVTableAddressPoint(Base, VTableClass); -} - llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); @@ -2088,8 +2080,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( ThisTy = D->getDestroyedType(); } - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, - QualType(), nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + nullptr, QualType(), nullptr); return nullptr; } @@ -2162,7 +2154,7 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, int64_t VirtualAdjustment, bool IsReturnAdjustment) { if (!NonVirtualAdjustment && !VirtualAdjustment) - return InitialPtr.getPointer(); + return InitialPtr.emitRawPointer(CGF); Address V = InitialPtr.withElementType(CGF.Int8Ty); @@ -2195,10 +2187,10 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, CGF.getPointerAlign()); } // Adjust our pointer. - ResultPtr = CGF.Builder.CreateInBoundsGEP( - V.getElementType(), V.getPointer(), Offset); + ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getElementType(), + V.emitRawPointer(CGF), Offset); } else { - ResultPtr = V.getPointer(); + ResultPtr = V.emitRawPointer(CGF); } // In a derived-to-base conversion, the non-virtual adjustment is @@ -2284,7 +2276,7 @@ Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie"); - CGF.Builder.CreateCall(F, NumElementsPtr.getPointer()); + CGF.Builder.CreateCall(F, NumElementsPtr.emitRawPointer(CGF)); } // Finally, compute a pointer to the actual data buffer by skipping @@ -2315,7 +2307,7 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, llvm::FunctionType::get(CGF.SizeTy, CGF.UnqualPtrTy, false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie"); - return CGF.Builder.CreateCall(F, numElementsPtr.getPointer()); + return CGF.Builder.CreateCall(F, numElementsPtr.emitRawPointer(CGF)); } CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { @@ -2627,7 +2619,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // Call __cxa_guard_release. This cannot throw. CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), - guardAddr.getPointer()); + guardAddr.emitRawPointer(CGF)); } else if (D.isLocalVarDecl()) { // For local variables, store 1 into the first byte of the guard variable // after the object initialization completes so that initialization is @@ -3120,10 +3112,10 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, LValue LV; if (VD->getType()->isReferenceType()) - LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType); + LV = CGF.MakeNaturalAlignRawAddrLValue(CallVal, LValType); else - LV = CGF.MakeAddrLValue(CallVal, LValType, - CGF.getContext().getDeclAlign(VD)); + LV = CGF.MakeRawAddrLValue(CallVal, LValType, + CGF.getContext().getDeclAlign(VD)); // FIXME: need setObjCGCLValueClass? return LV; } @@ -4604,7 +4596,7 @@ static void InitCatchParam(CodeGenFunction &CGF, CGF.Builder.CreateStore(Casted, ExnPtrTmp); // Bind the reference to the temporary. - AdjustedExn = ExnPtrTmp.getPointer(); + AdjustedExn = ExnPtrTmp.emitRawPointer(CGF); } } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 172c4c937b97..d38a26940a3c 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -327,10 +327,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -937,7 +933,7 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, } CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); - CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); + CPI->setArgOperand(2, var.getObjectAddress(CGF).emitRawPointer(CGF)); CGF.EHStack.pushCleanup(NormalCleanup, CPI); CGF.EmitAutoVarCleanups(var); } @@ -974,7 +970,7 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, llvm::Value *Offset = GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP( - Value.getElementType(), Value.getPointer(), Offset); + Value.getElementType(), Value.emitRawPointer(CGF), Offset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); return std::make_tuple(Address(Ptr, CGF.Int8Ty, VBaseAlign), Offset, @@ -1011,7 +1007,7 @@ llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, llvm::Type *StdTypeInfoPtrTy) { std::tie(ThisPtr, std::ignore, std::ignore) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); - llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()); + llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.emitRawPointer(CGF)); return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); } @@ -1033,7 +1029,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastCall( llvm::Value *Offset; std::tie(This, Offset, std::ignore) = performBaseAdjustment(CGF, This, SrcRecordTy); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = This.emitRawPointer(CGF); Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); // PVOID __RTDynamicCast( @@ -1065,7 +1061,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, llvm::FunctionCallee Function = CGF.CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), "__RTCastToVoid"); - llvm::Value *Args[] = {Value.getPointer()}; + llvm::Value *Args[] = {Value.emitRawPointer(CGF)}; return CGF.EmitRuntimeCall(Function, Args); } @@ -1493,7 +1489,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( llvm::Value *VBaseOffset = GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); llvm::Value *VBasePtr = CGF.Builder.CreateInBoundsGEP( - Result.getElementType(), Result.getPointer(), VBaseOffset); + Result.getElementType(), Result.emitRawPointer(CGF), VBaseOffset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); Result = Address(VBasePtr, CGF.Int8Ty, VBaseAlign); @@ -1660,7 +1656,8 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, llvm::Value *Implicit = getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating); // = nullptr - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, /*ImplicitParam=*/Implicit, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1791,13 +1788,6 @@ MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, return VFTablesMap[ID]; } -llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); - assert(VFTable && "Couldn't find a vftable for the given base?"); - return VFTable; -} - llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { // getAddrOfVTable may return 0 if asked to get an address of a vtable which @@ -2013,8 +2003,9 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( } This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, - ImplicitParam, Context.IntTy, CE); + RValue RV = + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } @@ -2212,13 +2203,13 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This, const ThisAdjustment &TA) { if (TA.isEmpty()) - return This.getPointer(); + return This.emitRawPointer(CGF); This = This.withElementType(CGF.Int8Ty); llvm::Value *V; if (TA.Virtual.isEmpty()) { - V = This.getPointer(); + V = This.emitRawPointer(CGF); } else { assert(TA.Virtual.Microsoft.VtordispOffset < 0); // Adjust the this argument based on the vtordisp value. @@ -2227,7 +2218,7 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); VtorDispPtr = VtorDispPtr.withElementType(CGF.Int32Ty); llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); - V = CGF.Builder.CreateGEP(This.getElementType(), This.getPointer(), + V = CGF.Builder.CreateGEP(This.getElementType(), This.emitRawPointer(CGF), CGF.Builder.CreateNeg(VtorDisp)); // Unfortunately, having applied the vtordisp means that we no @@ -2264,11 +2255,11 @@ llvm::Value * MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const ReturnAdjustment &RA) { if (RA.isEmpty()) - return Ret.getPointer(); + return Ret.emitRawPointer(CGF); Ret = Ret.withElementType(CGF.Int8Ty); - llvm::Value *V = Ret.getPointer(); + llvm::Value *V = Ret.emitRawPointer(CGF); if (RA.Virtual.Microsoft.VBIndex) { assert(RA.Virtual.Microsoft.VBIndex > 0); int32_t IntSize = CGF.getIntSize().getQuantity(); @@ -2583,7 +2574,7 @@ struct ResetGuardBit final : EHScopeStack::Cleanup { struct CallInitThreadAbort final : EHScopeStack::Cleanup { llvm::Value *Guard; - CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} + CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {} void Emit(CodeGenFunction &CGF, Flags flags) override { // Calling _Init_thread_abort will reset the guard's state. @@ -3123,8 +3114,8 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, llvm::Value **VBPtrOut) { CGBuilderTy &Builder = CGF.Builder; // Load the vbtable pointer from the vbptr in the instance. - llvm::Value *VBPtr = Builder.CreateInBoundsGEP(CGM.Int8Ty, This.getPointer(), - VBPtrOffset, "vbptr"); + llvm::Value *VBPtr = Builder.CreateInBoundsGEP( + CGM.Int8Ty, This.emitRawPointer(CGF), VBPtrOffset, "vbptr"); if (VBPtrOut) *VBPtrOut = VBPtr; @@ -3203,7 +3194,7 @@ llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( Builder.CreateBr(SkipAdjustBB); CGF.EmitBlock(SkipAdjustBB); llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); - Phi->addIncoming(Base.getPointer(), OriginalBB); + Phi->addIncoming(Base.emitRawPointer(CGF), OriginalBB); Phi->addIncoming(AdjustedBase, VBaseAdjustBB); return Phi; } @@ -3238,7 +3229,7 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - Addr = Base.getPointer(); + Addr = Base.emitRawPointer(CGF); } // Apply the offset, which we assume is non-null. @@ -3526,7 +3517,7 @@ CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - ThisPtrForCall = This.getPointer(); + ThisPtrForCall = This.emitRawPointer(CGF); } if (NonVirtualBaseAdjustment) @@ -4445,10 +4436,7 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { llvm::GlobalVariable *TI = getThrowInfo(ThrowType); // Call into the runtime to throw the exception. - llvm::Value *Args[] = { - AI.getPointer(), - TI - }; + llvm::Value *Args[] = {AI.emitRawPointer(CGF), TI}; CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); } diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 6893b50a3cfe..b1dfe5bf8f27 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -295,6 +295,11 @@ public: /// Get the AST address space for alloca. virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; } + Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, + LangAS SrcAddr, LangAS DestAddr, + llvm::Type *DestTy, + bool IsNonNull = false) const; + /// Perform address space cast of an expression of pointer type. /// \param V is the LLVM value to be casted to another address space. /// \param SrcAddr is the language address space of \p V. diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index 8718f1ecf3a7..7dce5042c3dc 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -85,7 +85,7 @@ private: LValue Src) { llvm::Value *Handle = nullptr; llvm::Constant *C = - llvm::dyn_cast(Src.getAddress(CGF).getPointer()); + llvm::dyn_cast(Src.getAddress(CGF).emitRawPointer(CGF)); // Lookup `addrspacecast` through the constant pointer if any. if (auto *ASC = llvm::dyn_cast_or_null(C)) C = llvm::cast(ASC->getPointerOperand()); diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 3eadb19bd205..174fddabbbdb 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -513,9 +513,10 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8); llvm::Value *RegOffset = Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity())); - RegAddr = Address( - Builder.CreateInBoundsGEP(CGF.Int8Ty, RegAddr.getPointer(), RegOffset), - DirectTy, RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); + RegAddr = Address(Builder.CreateInBoundsGEP( + CGF.Int8Ty, RegAddr.emitRawPointer(CGF), RegOffset), + DirectTy, + RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); // Increase the used-register count. NumRegs = @@ -551,7 +552,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Round up address of argument to alignment CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); if (Align > OverflowAreaAlign) { - llvm::Value *Ptr = OverflowArea.getPointer(); + llvm::Value *Ptr = OverflowArea.emitRawPointer(CGF); OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align), OverflowArea.getElementType(), Align); } @@ -560,7 +561,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Increase the overflow area. OverflowArea = Builder.CreateConstInBoundsByteGEP(OverflowArea, Size); - Builder.CreateStore(OverflowArea.getPointer(), OverflowAreaAddr); + Builder.CreateStore(OverflowArea.emitRawPointer(CGF), OverflowAreaAddr); CGF.EmitBranch(Cont); } diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index a337a52a94ec..9025a633f328 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -326,7 +326,7 @@ Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update VAList. Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); - Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); return ArgAddr.withElementType(ArgTy); } diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index 6eb0c6ef2f7d..deaafc85a315 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -306,7 +306,7 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update overflow_arg_area_ptr pointer llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( - OverflowArgArea.getElementType(), OverflowArgArea.getPointer(), + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); @@ -382,10 +382,9 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, Address MemAddr = RawMemAddr.withElementType(DirectTy); // Update overflow_arg_area_ptr pointer - llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), - OverflowArgArea.getPointer(), PaddedSizeV, - "overflow_arg_area"); + llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), + PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); CGF.EmitBranch(ContBlock); diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index aeb48f851e16..88edb781a947 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -180,7 +180,7 @@ Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Increment the VAList. if (!ArgSize.isZero()) { Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize); - Builder.CreateStore(APN.getPointer(), VAListAddr); + Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr); } return Val; diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 3a90eee5f1c9..aa20c758d84a 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -575,7 +575,7 @@ public: // Emit code to generate this result as a Value *. std::string asValue() override { if (AddressType) - return "(" + varname() + ".getPointer())"; + return "(" + varname() + ".emitRawPointer(*this))"; return Result::asValue(); } bool hasIntegerValue() const override { return Immediate; } diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 2a0c1e9e8c44..2e2ec9a1c830 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -2708,6 +2708,7 @@ public: IRBuilder(const IRBuilder &) = delete; InserterTy &getInserter() { return Inserter; } + const InserterTy &getInserter() const { return Inserter; } }; template -- GitLab From a515ea553f773cbb75e4aabeed7d05cc353345c8 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Thu, 28 Mar 2024 22:00:04 +0800 Subject: [PATCH 199/541] [OCaml] Fix buildbot failure caused by caa2258. NFC. Closes #86944. --- llvm/test/Bindings/OCaml/core.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/Bindings/OCaml/core.ml b/llvm/test/Bindings/OCaml/core.ml index a9abc9d17fe4..64bfa8ee412d 100644 --- a/llvm/test/Bindings/OCaml/core.ml +++ b/llvm/test/Bindings/OCaml/core.ml @@ -252,7 +252,7 @@ let test_constants () = group "constant arithmetic"; (* CHECK: @const_neg = global i64 sub * CHECK: @const_nsw_neg = global i64 sub nsw - * CHECK: @const_nuw_neg = global i64 sub nuw + * CHECK: @const_nuw_neg = global i64 sub * CHECK: @const_not = global i64 xor * CHECK: @const_add = global i64 add * CHECK: @const_nsw_add = global i64 add nsw -- GitLab From ff870aeeb7354fd3f681c17e248131e1065ac407 Mon Sep 17 00:00:00 2001 From: Alfie Richards Date: Thu, 28 Mar 2024 14:06:40 +0000 Subject: [PATCH 200/541] [ARM] Add reference to `ARMAsmParser` in `ARMOperand` (#86110) --- .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 495 +++++++++--------- 1 file changed, 258 insertions(+), 237 deletions(-) diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index d63e53df284b..028db9d17e30 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -72,15 +72,6 @@ using namespace llvm; -namespace llvm { -struct ARMInstrTable { - MCInstrDesc Insts[4445]; - MCOperandInfo OperandInfo[3026]; - MCPhysReg ImplicitOps[130]; -}; -extern const ARMInstrTable ARMDescs; -} // end namespace llvm - namespace { class ARMOperand; @@ -360,11 +351,6 @@ class ARMAsmParser : public MCTargetAsmParser { ITState.CurPosition = ~0U; } - // Return the low-subreg of a given Q register. - unsigned getDRegFromQReg(unsigned QReg) const { - return MRI->getSubReg(QReg, ARM::dsub_0); - } - // Get the condition code corresponding to the current IT block slot. ARMCC::CondCodes currentITCond() { unsigned MaskBit = extractITMaskBit(ITState.Mask, ITState.CurPosition); @@ -586,9 +572,6 @@ class ARMAsmParser : public MCTargetAsmParser { bool hasV8_1MMainline() const { return getSTI().hasFeature(ARM::HasV8_1MMainlineOps); } - bool hasMVE() const { - return getSTI().hasFeature(ARM::HasMVEIntegerOps); - } bool hasMVEFloat() const { return getSTI().hasFeature(ARM::HasMVEFloatOps); } @@ -768,6 +751,19 @@ public: void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override; void onLabelParsed(MCSymbol *Symbol) override; + + const MCInstrDesc &getInstrDesc(unsigned int Opcode) const { + return MII.get(Opcode); + } + + bool hasMVE() const { return getSTI().hasFeature(ARM::HasMVEIntegerOps); } + + // Return the low-subreg of a given Q register. + unsigned getDRegFromQReg(unsigned QReg) const { + return MRI->getSubReg(QReg, ARM::dsub_0); + } + + const MCRegisterInfo *getMRI() const { return MRI; } }; /// ARMOperand - Instances of this class represent a parsed ARM machine @@ -814,6 +810,8 @@ class ARMOperand : public MCParsedAsmOperand { SMLoc StartLoc, EndLoc, AlignmentLoc; SmallVector Registers; + ARMAsmParser *Parser; + struct CCOp { ARMCC::CondCodes Val; }; @@ -964,7 +962,7 @@ class ARMOperand : public MCParsedAsmOperand { }; public: - ARMOperand(KindTy K) : Kind(K) {} + ARMOperand(KindTy K, ARMAsmParser &Parser) : Kind(K), Parser(&Parser) {} /// getStartLoc - Get the location of the first token of this operand. SMLoc getStartLoc() const override { return StartLoc; } @@ -2043,6 +2041,11 @@ public: bool isProcIFlags() const { return Kind == k_ProcIFlags; } // NEON operands. + bool isAnyVectorList() const { + return Kind == k_VectorList || Kind == k_VectorListAllLanes || + Kind == k_VectorListIndexed; + } + bool isVectorList() const { return Kind == k_VectorList; } bool isSingleSpacedVectorList() const { @@ -2054,6 +2057,9 @@ public: } bool isVecListOneD() const { + // We convert a single D reg to a list containing a D reg + if (isDReg() && !Parser->hasMVE()) + return true; if (!isSingleSpacedVectorList()) return false; return VectorList.Count == 1; } @@ -2065,6 +2071,10 @@ public: } bool isVecListDPair() const { + // We convert a single Q reg to a list with the two corresponding D + // registers + if (isQReg() && !Parser->hasMVE()) + return true; if (!isSingleSpacedVectorList()) return false; return (ARMMCRegisterClasses[ARM::DPairRegClassID] .contains(VectorList.RegNum)); @@ -2542,8 +2552,7 @@ public: RegNum = 0; } else { unsigned NextOpIndex = Inst.getNumOperands(); - const MCInstrDesc &MCID = - ARMDescs.Insts[ARM::INSTRUCTION_LIST_END - 1 - Inst.getOpcode()]; + auto &MCID = Parser->getInstrDesc(Inst.getOpcode()); int TiedOp = MCID.getOperandConstraint(NextOpIndex, MCOI::TIED_TO); assert(TiedOp >= 0 && "Inactive register in vpred_r is not tied to an output!"); @@ -3378,7 +3387,21 @@ public: void addVecListOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); + + if (isAnyVectorList()) + Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); + else if (isDReg() && !Parser->hasMVE()) { + Inst.addOperand(MCOperand::createReg(Reg.RegNum)); + } else if (isQReg() && !Parser->hasMVE()) { + auto DPair = Parser->getDRegFromQReg(Reg.RegNum); + DPair = Parser->getMRI()->getMatchingSuperReg( + DPair, ARM::dsub_0, &ARMMCRegisterClasses[ARM::DPairRegClassID]); + Inst.addOperand(MCOperand::createReg(DPair)); + } else { + LLVM_DEBUG(dbgs() << "TYPE: " << Kind << "\n"); + llvm_unreachable( + "attempted to add a vector list register with wrong type!"); + } } void addMVEVecListOperands(MCInst &Inst, unsigned N) const { @@ -3607,67 +3630,72 @@ public: void print(raw_ostream &OS) const override; - static std::unique_ptr CreateITMask(unsigned Mask, SMLoc S) { - auto Op = std::make_unique(k_ITCondMask); + static std::unique_ptr CreateITMask(unsigned Mask, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_ITCondMask, Parser); Op->ITMask.Mask = Mask; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateCondCode(ARMCC::CondCodes CC, - SMLoc S) { - auto Op = std::make_unique(k_CondCode); + static std::unique_ptr + CreateCondCode(ARMCC::CondCodes CC, SMLoc S, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_CondCode, Parser); Op->CC.Val = CC; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateVPTPred(ARMVCC::VPTCodes CC, - SMLoc S) { - auto Op = std::make_unique(k_VPTPred); + static std::unique_ptr CreateVPTPred(ARMVCC::VPTCodes CC, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_VPTPred, Parser); Op->VCC.Val = CC; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateCoprocNum(unsigned CopVal, SMLoc S) { - auto Op = std::make_unique(k_CoprocNum); + static std::unique_ptr CreateCoprocNum(unsigned CopVal, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_CoprocNum, Parser); Op->Cop.Val = CopVal; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateCoprocReg(unsigned CopVal, SMLoc S) { - auto Op = std::make_unique(k_CoprocReg); + static std::unique_ptr CreateCoprocReg(unsigned CopVal, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_CoprocReg, Parser); Op->Cop.Val = CopVal; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateCoprocOption(unsigned Val, SMLoc S, - SMLoc E) { - auto Op = std::make_unique(k_CoprocOption); + static std::unique_ptr + CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_CoprocOption, Parser); Op->Cop.Val = Val; Op->StartLoc = S; Op->EndLoc = E; return Op; } - static std::unique_ptr CreateCCOut(unsigned RegNum, SMLoc S) { - auto Op = std::make_unique(k_CCOut); + static std::unique_ptr CreateCCOut(unsigned RegNum, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_CCOut, Parser); Op->Reg.RegNum = RegNum; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { - auto Op = std::make_unique(k_Token); + static std::unique_ptr CreateToken(StringRef Str, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_Token, Parser); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; @@ -3676,8 +3704,8 @@ public: } static std::unique_ptr CreateReg(unsigned RegNum, SMLoc S, - SMLoc E) { - auto Op = std::make_unique(k_Register); + SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_Register, Parser); Op->Reg.RegNum = RegNum; Op->StartLoc = S; Op->EndLoc = E; @@ -3686,9 +3714,9 @@ public: static std::unique_ptr CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, - unsigned ShiftReg, unsigned ShiftImm, SMLoc S, - SMLoc E) { - auto Op = std::make_unique(k_ShiftedRegister); + unsigned ShiftReg, unsigned ShiftImm, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_ShiftedRegister, Parser); Op->RegShiftedReg.ShiftTy = ShTy; Op->RegShiftedReg.SrcReg = SrcReg; Op->RegShiftedReg.ShiftReg = ShiftReg; @@ -3700,8 +3728,9 @@ public: static std::unique_ptr CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, - unsigned ShiftImm, SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_ShiftedImmediate); + unsigned ShiftImm, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_ShiftedImmediate, Parser); Op->RegShiftedImm.ShiftTy = ShTy; Op->RegShiftedImm.SrcReg = SrcReg; Op->RegShiftedImm.ShiftImm = ShiftImm; @@ -3711,8 +3740,9 @@ public: } static std::unique_ptr CreateShifterImm(bool isASR, unsigned Imm, - SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_ShifterImmediate); + SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_ShifterImmediate, Parser); Op->ShifterImm.isASR = isASR; Op->ShifterImm.Imm = Imm; Op->StartLoc = S; @@ -3720,9 +3750,9 @@ public: return Op; } - static std::unique_ptr CreateRotImm(unsigned Imm, SMLoc S, - SMLoc E) { - auto Op = std::make_unique(k_RotateImmediate); + static std::unique_ptr + CreateRotImm(unsigned Imm, SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_RotateImmediate, Parser); Op->RotImm.Imm = Imm; Op->StartLoc = S; Op->EndLoc = E; @@ -3730,8 +3760,9 @@ public: } static std::unique_ptr CreateModImm(unsigned Bits, unsigned Rot, - SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_ModifiedImmediate); + SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_ModifiedImmediate, Parser); Op->ModImm.Bits = Bits; Op->ModImm.Rot = Rot; Op->StartLoc = S; @@ -3740,17 +3771,20 @@ public: } static std::unique_ptr - CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_ConstantPoolImmediate); + CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_ConstantPoolImmediate, Parser); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; return Op; } - static std::unique_ptr - CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_BitfieldDescriptor); + static std::unique_ptr CreateBitfield(unsigned LSB, + unsigned Width, SMLoc S, + SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_BitfieldDescriptor, Parser); Op->Bitfield.LSB = LSB; Op->Bitfield.Width = Width; Op->StartLoc = S; @@ -3760,7 +3794,7 @@ public: static std::unique_ptr CreateRegList(SmallVectorImpl> &Regs, - SMLoc StartLoc, SMLoc EndLoc) { + SMLoc StartLoc, SMLoc EndLoc, ARMAsmParser &Parser) { assert(Regs.size() > 0 && "RegList contains no registers?"); KindTy Kind = k_RegisterList; @@ -3783,7 +3817,7 @@ public: assert(llvm::is_sorted(Regs) && "Register list must be sorted by encoding"); - auto Op = std::make_unique(Kind); + auto Op = std::make_unique(Kind, Parser); for (const auto &P : Regs) Op->Registers.push_back(P.second); @@ -3792,11 +3826,10 @@ public: return Op; } - static std::unique_ptr CreateVectorList(unsigned RegNum, - unsigned Count, - bool isDoubleSpaced, - SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_VectorList); + static std::unique_ptr + CreateVectorList(unsigned RegNum, unsigned Count, bool isDoubleSpaced, + SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_VectorList, Parser); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.isDoubleSpaced = isDoubleSpaced; @@ -3807,8 +3840,8 @@ public: static std::unique_ptr CreateVectorListAllLanes(unsigned RegNum, unsigned Count, bool isDoubleSpaced, - SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_VectorListAllLanes); + SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_VectorListAllLanes, Parser); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.isDoubleSpaced = isDoubleSpaced; @@ -3819,8 +3852,9 @@ public: static std::unique_ptr CreateVectorListIndexed(unsigned RegNum, unsigned Count, unsigned Index, - bool isDoubleSpaced, SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_VectorListIndexed); + bool isDoubleSpaced, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_VectorListIndexed, Parser); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.LaneIndex = Index; @@ -3830,9 +3864,10 @@ public: return Op; } - static std::unique_ptr - CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) { - auto Op = std::make_unique(k_VectorIndex); + static std::unique_ptr CreateVectorIndex(unsigned Idx, SMLoc S, + SMLoc E, MCContext &Ctx, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_VectorIndex, Parser); Op->VectorIndex.Val = Idx; Op->StartLoc = S; Op->EndLoc = E; @@ -3840,8 +3875,8 @@ public: } static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S, - SMLoc E) { - auto Op = std::make_unique(k_Immediate); + SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_Immediate, Parser); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; @@ -3851,8 +3886,9 @@ public: static std::unique_ptr CreateMem(unsigned BaseRegNum, const MCExpr *OffsetImm, unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, unsigned Alignment, - bool isNegative, SMLoc S, SMLoc E, SMLoc AlignmentLoc = SMLoc()) { - auto Op = std::make_unique(k_Memory); + bool isNegative, SMLoc S, SMLoc E, ARMAsmParser &Parser, + SMLoc AlignmentLoc = SMLoc()) { + auto Op = std::make_unique(k_Memory, Parser); Op->Memory.BaseRegNum = BaseRegNum; Op->Memory.OffsetImm = OffsetImm; Op->Memory.OffsetRegNum = OffsetRegNum; @@ -3868,8 +3904,8 @@ public: static std::unique_ptr CreatePostIdxReg(unsigned RegNum, bool isAdd, ARM_AM::ShiftOpc ShiftTy, - unsigned ShiftImm, SMLoc S, SMLoc E) { - auto Op = std::make_unique(k_PostIndexRegister); + unsigned ShiftImm, SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_PostIndexRegister, Parser); Op->PostIdxReg.RegNum = RegNum; Op->PostIdxReg.isAdd = isAdd; Op->PostIdxReg.ShiftTy = ShiftTy; @@ -3879,9 +3915,9 @@ public: return Op; } - static std::unique_ptr CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, - SMLoc S) { - auto Op = std::make_unique(k_MemBarrierOpt); + static std::unique_ptr + CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_MemBarrierOpt, Parser); Op->MBOpt.Val = Opt; Op->StartLoc = S; Op->EndLoc = S; @@ -3889,8 +3925,9 @@ public: } static std::unique_ptr - CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) { - auto Op = std::make_unique(k_InstSyncBarrierOpt); + CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_InstSyncBarrierOpt, Parser); Op->ISBOpt.Val = Opt; Op->StartLoc = S; Op->EndLoc = S; @@ -3898,33 +3935,36 @@ public: } static std::unique_ptr - CreateTraceSyncBarrierOpt(ARM_TSB::TraceSyncBOpt Opt, SMLoc S) { - auto Op = std::make_unique(k_TraceSyncBarrierOpt); + CreateTraceSyncBarrierOpt(ARM_TSB::TraceSyncBOpt Opt, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_TraceSyncBarrierOpt, Parser); Op->TSBOpt.Val = Opt; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateProcIFlags(ARM_PROC::IFlags IFlags, - SMLoc S) { - auto Op = std::make_unique(k_ProcIFlags); + static std::unique_ptr + CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S, ARMAsmParser &Parser) { + auto Op = std::make_unique(k_ProcIFlags, Parser); Op->IFlags.Val = IFlags; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateMSRMask(unsigned MMask, SMLoc S) { - auto Op = std::make_unique(k_MSRMask); + static std::unique_ptr CreateMSRMask(unsigned MMask, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_MSRMask, Parser); Op->MMask.Val = MMask; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr CreateBankedReg(unsigned Reg, SMLoc S) { - auto Op = std::make_unique(k_BankedReg); + static std::unique_ptr CreateBankedReg(unsigned Reg, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique(k_BankedReg, Parser); Op->BankedReg.Val = Reg; Op->StartLoc = S; Op->EndLoc = S; @@ -4328,12 +4368,11 @@ int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { } if (ShiftReg && ShiftTy != ARM_AM::rrx) - Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, - ShiftReg, Imm, - S, EndLoc)); + Operands.push_back(ARMOperand::CreateShiftedRegister( + ShiftTy, SrcReg, ShiftReg, Imm, S, EndLoc, *this)); else Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm, - S, EndLoc)); + S, EndLoc, *this)); return 0; } @@ -4352,12 +4391,13 @@ bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) { if (RegNo == -1) return true; - Operands.push_back(ARMOperand::CreateReg(RegNo, RegStartLoc, RegEndLoc)); + Operands.push_back( + ARMOperand::CreateReg(RegNo, RegStartLoc, RegEndLoc, *this)); const AsmToken &ExclaimTok = Parser.getTok(); if (ExclaimTok.is(AsmToken::Exclaim)) { Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), - ExclaimTok.getLoc())); + ExclaimTok.getLoc(), *this)); Parser.Lex(); // Eat exclaim token return false; } @@ -4382,9 +4422,8 @@ bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) { SMLoc E = Parser.getTok().getEndLoc(); Parser.Lex(); // Eat right bracket token. - Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), - SIdx, E, - getContext())); + Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), SIdx, E, + getContext(), *this)); } return false; @@ -4451,7 +4490,8 @@ ParseStatus ARMAsmParser::parseITCondCode(OperandVector &Operands) { return ParseStatus::NoMatch; Parser.Lex(); // Eat the token. - Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S)); + Operands.push_back( + ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S, *this)); return ParseStatus::Success; } @@ -4473,7 +4513,7 @@ ParseStatus ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { return ParseStatus::NoMatch; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); + Operands.push_back(ARMOperand::CreateCoprocNum(Num, S, *this)); return ParseStatus::Success; } @@ -4492,7 +4532,7 @@ ParseStatus ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { return ParseStatus::NoMatch; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); + Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S, *this)); return ParseStatus::Success; } @@ -4523,7 +4563,7 @@ ParseStatus ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) { SMLoc E = Parser.getTok().getEndLoc(); Parser.Lex(); // Eat the '}' - Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); + Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E, *this)); return ParseStatus::Success; } @@ -4726,11 +4766,12 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, Parser.Lex(); // Eat '}' token. // Push the register list operand. - Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); + Operands.push_back(ARMOperand::CreateRegList(Registers, S, E, *this)); // The ARM system instruction variants for LDM/STM have a '^' token here. if (Parser.getTok().is(AsmToken::Caret)) { - Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("^", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat '^' token. } @@ -4803,16 +4844,15 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { return Res; switch (LaneKind) { case NoLanes: - Operands.push_back(ARMOperand::CreateReg(Reg, S, E)); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E, *this)); break; case AllLanes: - Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, - S, E)); + Operands.push_back( + ARMOperand::CreateVectorListAllLanes(Reg, 1, false, S, E, *this)); break; case IndexedLane: - Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1, - LaneIndex, - false, S, E)); + Operands.push_back(ARMOperand::CreateVectorListIndexed( + Reg, 1, LaneIndex, false, S, E, *this)); break; } return ParseStatus::Success; @@ -4824,23 +4864,22 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { return Res; switch (LaneKind) { case NoLanes: - Operands.push_back(ARMOperand::CreateReg(Reg, S, E)); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E, *this)); break; case AllLanes: Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, &ARMMCRegisterClasses[ARM::DPairRegClassID]); - Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false, - S, E)); + Operands.push_back( + ARMOperand::CreateVectorListAllLanes(Reg, 2, false, S, E, *this)); break; case IndexedLane: - Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2, - LaneIndex, - false, S, E)); + Operands.push_back(ARMOperand::CreateVectorListIndexed( + Reg, 2, LaneIndex, false, S, E, *this)); break; } return ParseStatus::Success; } - Operands.push_back(ARMOperand::CreateReg(Reg, S, E)); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E, *this)); return ParseStatus::Success; } @@ -4994,14 +5033,12 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { } auto Create = (LaneKind == NoLanes ? ARMOperand::CreateVectorList : ARMOperand::CreateVectorListAllLanes); - Operands.push_back(Create(FirstReg, Count, (Spacing == 2), S, E)); + Operands.push_back(Create(FirstReg, Count, (Spacing == 2), S, E, *this)); break; } case IndexedLane: - Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count, - LaneIndex, - (Spacing == 2), - S, E)); + Operands.push_back(ARMOperand::CreateVectorListIndexed( + FirstReg, Count, LaneIndex, (Spacing == 2), S, E, *this)); break; } return ParseStatus::Success; @@ -5068,7 +5105,8 @@ ParseStatus ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { } else return ParseStatus::Failure; - Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); + Operands.push_back( + ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S, *this)); return ParseStatus::Success; } @@ -5086,7 +5124,8 @@ ARMAsmParser::parseTraceSyncBarrierOptOperand(OperandVector &Operands) { Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateTraceSyncBarrierOpt(ARM_TSB::CSYNC, S)); + Operands.push_back( + ARMOperand::CreateTraceSyncBarrierOpt(ARM_TSB::CSYNC, S, *this)); return ParseStatus::Success; } @@ -5131,7 +5170,7 @@ ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { return ParseStatus::Failure; Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt( - (ARM_ISB::InstSyncBOpt)Opt, S)); + (ARM_ISB::InstSyncBOpt)Opt, S, *this)); return ParseStatus::Success; } @@ -5165,7 +5204,8 @@ ParseStatus ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { } Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); + Operands.push_back( + ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S, *this)); return ParseStatus::Success; } @@ -5186,7 +5226,7 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { } unsigned SYSmvalue = Val & 0xFF; Parser.Lex(); - Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); + Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S, *this)); return ParseStatus::Success; } @@ -5202,7 +5242,7 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { unsigned SYSmvalue = TheReg->Encoding & 0xFFF; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); + Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S, *this)); return ParseStatus::Success; } @@ -5265,7 +5305,7 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { FlagsVal |= 16; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); + Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S, *this)); return ParseStatus::Success; } @@ -5289,7 +5329,7 @@ ParseStatus ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { unsigned Encoding = TheReg->Encoding; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S)); + Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S, *this)); return ParseStatus::Success; } @@ -5331,7 +5371,7 @@ ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, if (Val < Low || Val > High) return Error(Loc, "immediate value out of range"); - Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc)); + Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc, *this)); return ParseStatus::Success; } @@ -5350,9 +5390,8 @@ ParseStatus ARMAsmParser::parseSetEndImm(OperandVector &Operands) { if (Val == -1) return Error(S, "'be' or 'le' operand expected"); - Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::create(Val, - getContext()), - S, Tok.getEndLoc())); + Operands.push_back(ARMOperand::CreateImm( + MCConstantExpr::create(Val, getContext()), S, Tok.getEndLoc(), *this)); return ParseStatus::Success; } @@ -5407,7 +5446,8 @@ ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { return Error(ExLoc, "'lsr' shift amount must be in range [0,31]"); } - Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc)); + Operands.push_back( + ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc, *this)); return ParseStatus::Success; } @@ -5448,7 +5488,7 @@ ParseStatus ARMAsmParser::parseRotImm(OperandVector &Operands) { if (Val != 8 && Val != 16 && Val != 24 && Val != 0) return Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24"); - Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc)); + Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc, *this)); return ParseStatus::Success; } @@ -5498,9 +5538,8 @@ ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { int Enc = ARM_AM::getSOImmVal(Imm1); if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) { // We have a match! - Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF), - (Enc & 0xF00) >> 7, - Sx1, Ex1)); + Operands.push_back(ARMOperand::CreateModImm( + (Enc & 0xFF), (Enc & 0xF00) >> 7, Sx1, Ex1, *this)); return ParseStatus::Success; } @@ -5511,13 +5550,13 @@ ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { // instruction with a mod_imm operand. The alias is defined such that the // parser method is shared, that's why we have to do this here. if (Parser.getTok().is(AsmToken::EndOfStatement)) { - Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); + Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1, *this)); return ParseStatus::Success; } } else { // Operands like #(l1 - l2) can only be evaluated at a later stage (via an // MCFixup). Fallback to a plain immediate. - Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); + Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1, *this)); return ParseStatus::Success; } @@ -5551,7 +5590,7 @@ ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { Imm2 = CE->getValue(); if (!(Imm2 & ~0x1E)) { // We have a match! - Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2)); + Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2, *this)); return ParseStatus::Success; } return Error(Sx2, @@ -5606,7 +5645,7 @@ ParseStatus ARMAsmParser::parseBitfield(OperandVector &Operands) { if (Width < 1 || Width > 32 - LSB) return Error(E, "'width' operand must be in the range [1,32-lsb]"); - Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc)); + Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc, *this)); return ParseStatus::Success; } @@ -5653,8 +5692,8 @@ ParseStatus ARMAsmParser::parsePostIdxReg(OperandVector &Operands) { E = Parser.getTok().getLoc(); } - Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, - ShiftImm, S, E)); + Operands.push_back( + ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, ShiftImm, S, E, *this)); return ParseStatus::Success; } @@ -5695,8 +5734,8 @@ ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { if (isNegative && Val == 0) Val = std::numeric_limits::min(); - Operands.push_back( - ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, E)); + Operands.push_back(ARMOperand::CreateImm( + MCConstantExpr::create(Val, getContext()), S, E, *this)); return ParseStatus::Success; } @@ -5720,8 +5759,8 @@ ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { return Error(Tok.getLoc(), "register expected"); } - Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift, - 0, S, Tok.getEndLoc())); + Operands.push_back(ARMOperand::CreatePostIdxReg( + Reg, isAdd, ARM_AM::no_shift, 0, S, Tok.getEndLoc(), *this)); return ParseStatus::Success; } @@ -5780,7 +5819,8 @@ void ARMAsmParser::cvtThumbMultiply(MCInst &Inst, if (CondOutI != 0) { ((ARMOperand &)*Operands[CondOutI]).addCCOutOperands(Inst, 1); } else { - ARMOperand Op = *ARMOperand::CreateCCOut(0, Operands[0]->getEndLoc()); + ARMOperand Op = + *ARMOperand::CreateCCOut(0, Operands[0]->getEndLoc(), *this); Op.addCCOutOperands(Inst, 1); } // Rn @@ -5792,8 +5832,8 @@ void ARMAsmParser::cvtThumbMultiply(MCInst &Inst, if (CondI != 0) { ((ARMOperand &)*Operands[CondI]).addCondCodeOperands(Inst, 2); } else { - ARMOperand Op = - *ARMOperand::CreateCondCode(llvm::ARMCC::AL, Operands[0]->getEndLoc()); + ARMOperand Op = *ARMOperand::CreateCondCode( + llvm::ARMCC::AL, Operands[0]->getEndLoc(), *this); Op.addCondCodeOperands(Inst, 2); } } @@ -5849,8 +5889,8 @@ void ARMAsmParser::cvtThumbBranches(MCInst &Inst, if (CondI != 0) { ((ARMOperand &)*Operands[CondI]).addCondCodeOperands(Inst, 2); } else { - ARMOperand Op = - *ARMOperand::CreateCondCode(llvm::ARMCC::AL, Operands[0]->getEndLoc()); + ARMOperand Op = *ARMOperand::CreateCondCode( + llvm::ARMCC::AL, Operands[0]->getEndLoc(), *this); Op.addCondCodeOperands(Inst, 2); } } @@ -5879,7 +5919,7 @@ void ARMAsmParser::cvtMVEVMOVQtoDReg( .addCondCodeOperands(Inst, 2); // condition code } else { ARMOperand Op = - *ARMOperand::CreateCondCode(ARMCC::AL, Operands[0]->getEndLoc()); + *ARMOperand::CreateCondCode(ARMCC::AL, Operands[0]->getEndLoc(), *this); Op.addCondCodeOperands(Inst, 2); } } @@ -5909,14 +5949,14 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { E = Tok.getEndLoc(); Parser.Lex(); // Eat right bracket token. - Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, - ARM_AM::no_shift, 0, 0, false, - S, E)); + Operands.push_back(ARMOperand::CreateMem( + BaseRegNum, nullptr, 0, ARM_AM::no_shift, 0, 0, false, S, E, *this)); // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. It's rather odd, but syntactically valid. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -5967,13 +6007,14 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { // Don't worry about range checking the value here. That's handled by // the is*() predicates. Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, - ARM_AM::no_shift, 0, Align, - false, S, E, AlignmentLoc)); + ARM_AM::no_shift, 0, Align, false, + S, E, *this, AlignmentLoc)); // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -6009,8 +6050,9 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { AdjustedOffset = CE; } else AdjustedOffset = Offset; - Operands.push_back(ARMOperand::CreateMem( - BaseRegNum, AdjustedOffset, 0, ARM_AM::no_shift, 0, 0, false, S, E)); + Operands.push_back(ARMOperand::CreateMem(BaseRegNum, AdjustedOffset, 0, + ARM_AM::no_shift, 0, 0, false, S, + E, *this)); // Now we should have the closing ']' if (Parser.getTok().isNot(AsmToken::RBrac)) @@ -6021,7 +6063,8 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -6060,12 +6103,13 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, OffsetRegNum, ShiftType, ShiftImm, 0, isNegative, - S, E)); + S, E, *this)); // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -6203,9 +6247,9 @@ ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { // If we had a '-' in front, toggle the sign bit. IntVal ^= (uint64_t)isNegative << 31; Parser.Lex(); // Eat the token. - Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::create(IntVal, getContext()), - S, Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateImm(MCConstantExpr::create(IntVal, getContext()), S, + Parser.getTok().getLoc(), *this)); return ParseStatus::Success; } // Also handle plain integers. Instructions which allow floating point @@ -6218,9 +6262,9 @@ ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { float RealVal = ARM_AM::getFPImmFloat(Val); Val = APFloat(RealVal).bitcastToAPInt().getZExtValue(); - Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::create(Val, getContext()), S, - Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, + Parser.getTok().getLoc(), *this)); return ParseStatus::Success; } @@ -6266,7 +6310,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { Parser.getTok().getString().equals_insensitive("apsr_nzcv")) { S = Parser.getTok().getLoc(); Parser.Lex(); - Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S)); + Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S, *this)); return false; } } @@ -6286,7 +6330,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (getParser().parseExpression(IdVal)) return true; E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(IdVal, S, E)); + Operands.push_back(ARMOperand::CreateImm(IdVal, S, E, *this)); return false; } case AsmToken::LBrac: @@ -6330,14 +6374,14 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { getContext()); } E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); + Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E, *this)); // There can be a trailing '!' on operands that we want as a separate // '!' Token operand. Handle that here. For example, the compatibility // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), - Parser.getTok().getLoc())); + Operands.push_back(ARMOperand::CreateToken( + Parser.getTok().getString(), Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat exclaim token } return false; @@ -6362,7 +6406,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { const MCExpr *ExprVal = ARMMCExpr::create(RefKind, SubExprVal, getContext()); E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); + Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E, *this)); return false; } case AsmToken::Equal: { @@ -6377,7 +6421,8 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { // execute-only: we assume that assembly programmers know what they are // doing and allow literal pool creation here - Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E)); + Operands.push_back( + ARMOperand::CreateConstantPoolImm(SubExprVal, S, E, *this)); return false; } } @@ -6913,9 +6958,9 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, (PairedReg == ARM::SP && !hasV8Ops())) return; - Operands.insert( - Operands.begin() + IdX + 1, - ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc())); + Operands.insert(Operands.begin() + IdX + 1, + ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), + Op2.getEndLoc(), *this)); } // Dual-register instruction have the following syntax: @@ -6975,7 +7020,7 @@ bool ARMAsmParser::CDEConvertDualRegOperand(StringRef Mnemonic, Operands.erase(Operands.begin() + MnemonicOpsEndInd + 2); Operands[MnemonicOpsEndInd + 1] = - ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc()); + ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc(), *this); return false; } @@ -7048,7 +7093,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, return Error(NameLoc, "conditional execution not supported in Thumb1"); } - Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc)); + Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc, *this)); // Handle the mask for IT and VPT instructions. In ARMOperand and // MCOperand, this is stored in a format independent of the @@ -7080,7 +7125,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (Pos == 'e') Mask |= 8; } - Operands.push_back(ARMOperand::CreateITMask(Mask, Loc)); + Operands.push_back(ARMOperand::CreateITMask(Mask, Loc, *this)); } // FIXME: This is all a pretty gross hack. We should automatically handle @@ -7120,8 +7165,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Add the carry setting operand, if necessary. if (CanAcceptCarrySet && CarrySetting) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size()); - Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, - Loc)); + Operands.push_back( + ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, Loc, *this)); } // Add the predication code operand, if necessary. @@ -7129,7 +7174,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + CarrySetting); Operands.push_back(ARMOperand::CreateCondCode( - ARMCC::CondCodes(PredicationCode), Loc)); + ARMCC::CondCodes(PredicationCode), Loc, *this)); } // Add the VPT predication code operand, if necessary. @@ -7141,14 +7186,14 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + CarrySetting); Operands.push_back(ARMOperand::CreateVPTPred( - ARMVCC::VPTCodes(VPTPredicationCode), Loc)); + ARMVCC::VPTCodes(VPTPredicationCode), Loc, *this)); } // Add the processor imod operand, if necessary. if (ProcessorIMod) { Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::create(ProcessorIMod, getContext()), - NameLoc, NameLoc)); + MCConstantExpr::create(ProcessorIMod, getContext()), NameLoc, NameLoc, + *this)); } else if (Mnemonic == "cps" && isMClass()) { return Error(NameLoc, "instruction 'cps' requires effect for M-class"); } @@ -7177,7 +7222,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // so discard it to avoid errors that can be caused by the matcher. if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); - Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc)); + Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc, *this)); } } @@ -7236,9 +7281,9 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() - 1 + CarrySetting); Operands.insert(Operands.begin(), - ARMOperand::CreateVPTPred(ARMVCC::None, PLoc)); - Operands.insert(Operands.begin(), - ARMOperand::CreateToken(StringRef("vmovlt"), MLoc)); + ARMOperand::CreateVPTPred(ARMVCC::None, PLoc, *this)); + Operands.insert(Operands.begin(), ARMOperand::CreateToken( + StringRef("vmovlt"), MLoc, *this)); } else if (Mnemonic == "vcvt" && PredicationCode == ARMCC::NE && !shouldOmitVectorPredicateOperand(Mnemonic, Operands, MnemonicOpsEndInd)) { @@ -7252,9 +7297,9 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() - 1 + CarrySetting); Operands.insert(Operands.begin(), - ARMOperand::CreateVPTPred(ARMVCC::Else, PLoc)); + ARMOperand::CreateVPTPred(ARMVCC::Else, PLoc, *this)); Operands.insert(Operands.begin(), - ARMOperand::CreateToken(StringRef("vcvtn"), MLoc)); + ARMOperand::CreateToken(StringRef("vcvtn"), MLoc, *this)); } else if (Mnemonic == "vmul" && PredicationCode == ARMCC::LT && !shouldOmitVectorPredicateOperand(Mnemonic, Operands, MnemonicOpsEndInd)) { @@ -7264,8 +7309,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, removeCondCode(Operands, MnemonicOpsEndInd); Operands.erase(Operands.begin()); SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); - Operands.insert(Operands.begin(), - ARMOperand::CreateToken(StringRef("vmullt"), MLoc)); + Operands.insert(Operands.begin(), ARMOperand::CreateToken( + StringRef("vmullt"), MLoc, *this)); } else if (Mnemonic.starts_with("vcvt") && !Mnemonic.starts_with("vcvta") && !Mnemonic.starts_with("vcvtn") && !Mnemonic.starts_with("vcvtp") && @@ -7291,7 +7336,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Mnemonic = Mnemonic.substr(0, 4); Operands.insert(Operands.begin(), - ARMOperand::CreateToken(Mnemonic, MLoc)); + ARMOperand::CreateToken(Mnemonic, MLoc, *this)); } } SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + @@ -7299,7 +7344,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Add VPTPred Operands.insert(Operands.begin() + 1, ARMOperand::CreateVPTPred( - ARMVCC::VPTCodes(VPTPredicationCode), PLoc)); + ARMVCC::VPTCodes(VPTPredicationCode), PLoc, *this)); ++MnemonicOpsEndInd; } } else if (CanAcceptVPTPredicationCode) { @@ -7329,7 +7374,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Mnemonic = Name.slice(0, Mnemonic.size() + 1); Operands.erase(Operands.begin()); Operands.insert(Operands.begin(), - ARMOperand::CreateToken(Mnemonic, NameLoc)); + ARMOperand::CreateToken(Mnemonic, NameLoc, *this)); } } @@ -7383,9 +7428,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, unsigned NewReg = MRI->getMatchingSuperReg( Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); - - Operands[Idx] = - ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc()); + Operands[Idx] = ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), + Op2.getEndLoc(), *this); Operands.erase(Operands.begin() + Idx + 1); } } @@ -7404,7 +7448,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, static_cast(*Operands[MnemonicOpsEndInd + 1]).getReg() == ARM::LR && static_cast(*Operands[MnemonicOpsEndInd + 2]).isImm()) { - Operands.front() = ARMOperand::CreateToken(Name, NameLoc); + Operands.front() = ARMOperand::CreateToken(Name, NameLoc, *this); removeCCOut(Operands, MnemonicOpsEndInd); } return false; @@ -13003,29 +13047,6 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP) return Match_Success; return Match_rGPR; - // Note: This mutates the operand which could cause issues for future - // matches if this one fails later. - // It would be better to do this in addVecList but as this doesn't have access - // to MRI this isn't possible. - // If trying to match a VecListDPair with a Q register, convert Q to list. - case MCK_VecListDPair: - if (Op.isQReg() && !hasMVE()) { - auto DPair = getDRegFromQReg(Op.getReg()); - DPair = MRI->getMatchingSuperReg( - DPair, ARM::dsub_0, &ARMMCRegisterClasses[ARM::DPairRegClassID]); - Op.setVecListDPair(DPair); - return Match_Success; - } - return Match_InvalidOperand; - // Note: This mutates the operand (see above). - // If trying to match a VecListDPair with a D register, convert D singleton - // list. - case MCK_VecListOneD: - if (Op.isDReg() && !hasMVE()) { - Op.setVecListOneD(Op.getReg()); - return Match_Success; - } - return Match_InvalidOperand; } return Match_InvalidOperand; } @@ -13075,13 +13096,13 @@ bool ARMAsmParser::isMnemonicVPTPredicable(StringRef Mnemonic, } std::unique_ptr ARMAsmParser::defaultCondCodeOp() { - return ARMOperand::CreateCondCode(ARMCC::AL, SMLoc()); + return ARMOperand::CreateCondCode(ARMCC::AL, SMLoc(), *this); } std::unique_ptr ARMAsmParser::defaultCCOutOp() { - return ARMOperand::CreateCCOut(0, SMLoc()); + return ARMOperand::CreateCCOut(0, SMLoc(), *this); } std::unique_ptr ARMAsmParser::defaultVPTPredOp() { - return ARMOperand::CreateVPTPred(ARMVCC::None, SMLoc()); + return ARMOperand::CreateVPTPred(ARMVCC::None, SMLoc(), *this); } -- GitLab From d7975c9d93fb4a69c0bd79d7d5b3f6be77a25c73 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 28 Mar 2024 10:35:15 -0400 Subject: [PATCH 201/541] [SLP]Add better minbitwidth analysis for udiv/urem instructions. Adds improved bitwidth analysis for udiv/urem instructions. The analysis is based on similar version in InstCombiner. Reviewers: RKSimon Reviewed By: RKSimon Pull Request: https://github.com/llvm/llvm-project/pull/85928 --- .../Transforms/Vectorize/SLPVectorizer.cpp | 22 +++++++++++++++++++ .../X86/reorder-possible-strided-node.ll | 8 ++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 961380ce4ad9..c055091feeb4 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -14190,6 +14190,28 @@ bool BoUpSLP::collectValuesToDemote( return false; break; } + case Instruction::UDiv: + case Instruction::URem: { + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; + // UDiv and URem can be truncated if all the truncated bits are zero. + if (!AttemptCheckBitwidth( + [&](unsigned BitWidth, unsigned OrigBitWidth) { + assert(BitWidth <= OrigBitWidth && "Unexpected bitwidths!"); + APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); + return MaskedValueIsZero(I->getOperand(0), Mask, + SimplifyQuery(*DL)) && + MaskedValueIsZero(I->getOperand(1), Mask, + SimplifyQuery(*DL)); + }, + NeedToExit)) + return false; + if (NeedToExit) + return true; + if (!ProcessOperands({I->getOperand(0), I->getOperand(1)}, NeedToExit)) + return false; + break; + } // We can demote selects if we can demote their true and false values. case Instruction::Select: { diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll b/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll index 4a23abf182e8..cfbbe14186b5 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll @@ -116,9 +116,7 @@ define void @test_div() { ; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[ARRAYIDX22]], align 4 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> ; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i32> [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i32> [[TMP3]] to <4 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = udiv <4 x i64> [[TMP4]], -; CHECK-NEXT: [[TMP6:%.*]] = trunc <4 x i64> [[TMP5]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = udiv <4 x i32> [[TMP3]], ; CHECK-NEXT: store <4 x i32> [[TMP6]], ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 ; CHECK-NEXT: ret void ; @@ -170,9 +168,7 @@ define void @test_rem() { ; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[ARRAYIDX22]], align 4 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> ; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i32> [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i32> [[TMP3]] to <4 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = urem <4 x i64> [[TMP4]], -; CHECK-NEXT: [[TMP6:%.*]] = trunc <4 x i64> [[TMP5]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = urem <4 x i32> [[TMP3]], ; CHECK-NEXT: store <4 x i32> [[TMP6]], ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 ; CHECK-NEXT: ret void ; -- GitLab From d7753989eaa38e8b7a4ff01d8fced726eea3e34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= Date: Thu, 28 Mar 2024 14:52:08 +0000 Subject: [PATCH 202/541] [mlir][linalg] Add e2e test for linalg.mmt4d + pack/unpack (#84964) This is a follow-up for #81790. This patch basically extends: * test/Integration/Dialect/Linalg/CPU/mmt4d.mlir with pack/unpack ops so that to overall computation is a matrix multiplication (as opposed to linalg.mmt4d). For comparison (and to make it easier to verify correctness), linalg.matmul is also included in the test. --- .../Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 mlir/test/Integration/Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir new file mode 100644 index 000000000000..5680882dccb1 --- /dev/null +++ b/mlir/test/Integration/Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir @@ -0,0 +1,173 @@ +// DEFINE: %{compile} = mlir-opt %s \ +// DEFINE: -transform-interpreter -test-transform-dialect-erase-schedule \ +// DEFINE: -one-shot-bufferize="bufferize-function-boundaries" \ +// DEFINE: -buffer-deallocation-pipeline="private-function-dynamic-ownership" \ +// DEFINE: -cse -canonicalize -test-lower-to-llvm +// DEFINE: %{entry_point} = main +// DEFINE: %{run} = mlir-cpu-runner -e %{entry_point} -entry-point-result=void \ +// DEFINE: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils + +// RUN: %{compile} | %{run} | FileCheck %s + +/// End-to-end test for computing matrix-multiplication using linalg.mmt4d. In +/// particular, demonstrates how the following MLIR sequence (implemented in @mmt4d): +/// +/// A_pack = tensor.pack A +/// B_pack = tensor.pack B +/// C_pack = tensor.pack C +/// out_pack = linalg.mmt4d(A_pack, B_pack, C_pack) +/// +/// is equivalent to: +/// +/// linalg.matmul(A, B, C) +/// +/// (implemented in @matmul). + +func.func @main() { + // Allocate and initialise the inputs + %A_alloc = tensor.empty() : tensor<7x16xi32> + %B_alloc = tensor.empty() : tensor<16x13xi32> + + %three = arith.constant 3 : i32 + %four = arith.constant 4 : i32 + %A = linalg.fill ins(%three : i32) outs(%A_alloc : tensor<7x16xi32>) -> tensor<7x16xi32> + %B = linalg.fill ins(%four : i32) outs(%B_alloc : tensor<16x13xi32>) -> tensor<16x13xi32> + %C = arith.constant dense<[ + [ 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85], + [ 2, 9, 16, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86], + [ 3, 10, 17, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87], + [ 4, 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88], + [ 5, 12, 19, 26, 33, 40, 47, 54, 61, 68, 75, 82, 89], + [ 6, 13, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90], + [ 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91] + ]> : tensor<7x13xi32> + + // Matrix multiplication via linalg.mmt4d + // CHECK: Unranked Memref + // CHECK: [193, 200, 207, 214, 221, 228, 235, 242, 249, 256, 263, 270, 277] + // CHECK: [194, 201, 208, 215, 222, 229, 236, 243, 250, 257, 264, 271, 278] + // CHECK: [195, 202, 209, 216, 223, 230, 237, 244, 251, 258, 265, 272, 279] + // CHECK: [196, 203, 210, 217, 224, 231, 238, 245, 252, 259, 266, 273, 280] + // CHECK: [197, 204, 211, 218, 225, 232, 239, 246, 253, 260, 267, 274, 281] + // CHECK: [198, 205, 212, 219, 226, 233, 240, 247, 254, 261, 268, 275, 282] + // CHECK: [199, 206, 213, 220, 227, 234, 241, 248, 255, 262, 269, 276, 283] + %C_mmt4d = func.call @mmt4d(%A, %B, %C) : (tensor<7x16xi32>, tensor<16x13xi32>, tensor<7x13xi32>) -> tensor<7x13xi32> + %xf = tensor.cast %C_mmt4d : tensor<7x13xi32> to tensor<*xi32> + call @printMemrefI32(%xf) : (tensor<*xi32>) -> () + + // Matrix multiplication with linalg.matmul + // CHECK: Unranked Memref + // CHECK: [193, 200, 207, 214, 221, 228, 235, 242, 249, 256, 263, 270, 277] + // CHECK: [194, 201, 208, 215, 222, 229, 236, 243, 250, 257, 264, 271, 278] + // CHECK: [195, 202, 209, 216, 223, 230, 237, 244, 251, 258, 265, 272, 279] + // CHECK: [196, 203, 210, 217, 224, 231, 238, 245, 252, 259, 266, 273, 280] + // CHECK: [197, 204, 211, 218, 225, 232, 239, 246, 253, 260, 267, 274, 281] + // CHECK: [198, 205, 212, 219, 226, 233, 240, 247, 254, 261, 268, 275, 282] + // CHECK: [199, 206, 213, 220, 227, 234, 241, 248, 255, 262, 269, 276, 283] + %C_matmul = func.call @matmul(%A, %B, %C) : (tensor<7x16xi32>, tensor<16x13xi32>, tensor<7x13xi32>) -> tensor<7x13xi32> + %xf_2 = tensor.cast %C_matmul : tensor<7x13xi32> to tensor<*xi32> + call @printMemrefI32(%xf_2) : (tensor<*xi32>) -> () + + return +} + +func.func private @matmul(%A: tensor<7x16xi32>, %B: tensor<16x13xi32>, %C: tensor<7x13xi32>) -> tensor<7x13xi32> { + %C_matmul = linalg.matmul ins(%A, %B: tensor<7x16xi32>, tensor<16x13xi32>) + outs(%C: tensor<7x13xi32>) -> tensor<7x13xi32> + + return %C_matmul : tensor<7x13xi32> +} + +func.func private @mmt4d(%A: tensor<7x16xi32>, %B: tensor<16x13xi32>, %C: tensor<7x13xi32>) -> tensor<7x13xi32> { + %zero = arith.constant 0 : i32 + + %A_pack_empty = tensor.empty() : tensor<2x16x8x1xi32> + %B_pack_empty = tensor.empty() : tensor<2x16x8x1xi32> + %C_pack_empty = tensor.empty() : tensor<2x2x8x8xi32> + + // Pack matrices + %A_pack = tensor.pack %A padding_value(%zero : i32) inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %A_pack_empty : tensor<7x16xi32> -> tensor<2x16x8x1xi32> + %B_pack = tensor.pack %B padding_value(%zero : i32) outer_dims_perm = [1, 0] inner_dims_pos = [1, 0] inner_tiles = [8, 1] into %B_pack_empty : tensor<16x13xi32> -> tensor<2x16x8x1xi32> + %C_pack = tensor.pack %C padding_value(%zero : i32) outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %C_pack_empty : tensor<7x13xi32> -> tensor<2x2x8x8xi32> + + // MMT4D + %mmt4d = linalg.mmt4d ins(%A_pack, %B_pack : tensor<2x16x8x1xi32>, tensor<2x16x8x1xi32>) outs(%C_pack : tensor<2x2x8x8xi32>) -> tensor<2x2x8x8xi32> + + // Unpack output + %C_out_empty = tensor.empty() : tensor<7x13xi32> + %C_out_unpack = tensor.unpack %mmt4d outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %C_out_empty : tensor<2x2x8x8xi32> -> tensor<7x13xi32> + + return %C_out_unpack : tensor<7x13xi32> +} + +module @transforms attributes { transform.with_named_sequence } { + transform.named_sequence @__transform_main(%module: !transform.any_op {transform.readonly}) { + %mmt4d = transform.collect_matching @match_mmt4d in %module : (!transform.any_op) -> (!transform.any_op) + %func = transform.get_parent_op %mmt4d {isolated_from_above} : (!transform.any_op) -> !transform.op<"func.func"> + + // Step 1: Tile + // Tile parallel dims + %tiled_linalg_op_p, %loops:4 = transform.structured.tile_using_for %mmt4d[1, 1, 0, 8, 8, 0] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op) + // Tile reduction dims + %tiled_linalg_op_r, %loops2:2 = transform.structured.tile_using_for %tiled_linalg_op_p[0, 0, 1, 0, 0, 1] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op) + + // Step 2: Vectorize + transform.structured.vectorize %tiled_linalg_op_r : !transform.any_op + + // Step 3: Simplify + // vector.multi_reduction --> vector.contract + // Generates a 6-dim vector.contract with the dim matching the original MMT4D Op + // and with the following split into parallel and reduction dims: + // * parallel, parallel, reduction, parallel, parallel, reduction + transform.apply_patterns to %func { + transform.apply_patterns.vector.reduction_to_contract + // Reduce the rank of xfer ops. This transforms vector.contract to be + // more matmul-like and to enable the lowering to outer product Ops. + transform.apply_patterns.vector.transfer_permutation_patterns + } : !transform.op<"func.func"> + + // Hoisting and LICM - not strictly required + %func_h = transform.structured.hoist_redundant_vector_transfers %func + : (!transform.op<"func.func">) -> !transform.op<"func.func"> + %all_loops = transform.structured.match interface{LoopLikeInterface} in %func_h + : (!transform.op<"func.func">) -> !transform.any_op + transform.apply_licm to %all_loops : !transform.any_op + transform.loop.hoist_loop_invariant_subsets %all_loops : !transform.any_op + + // Simplify the 6-dim vector.contract into a 3-dim matmul-like + // vector.contract with the following split into parallel and reduction + // dims: + // * parallel, parallel, reduction + transform.apply_patterns to %func_h { + transform.apply_patterns.vector.reduction_to_contract + transform.apply_patterns.vector.cast_away_vector_leading_one_dim + transform.apply_patterns.canonicalization + } : !transform.op<"func.func"> + + // Step 4. Lower tensor.pack + %pack = transform.structured.match ops{["tensor.pack"]} in %func_h + : (!transform.op<"func.func">) -> !transform.op<"tensor.pack"> + transform.structured.lower_pack %pack : (!transform.op<"tensor.pack">) + -> (!transform.op<"tensor.pad">, !transform.op<"tensor.expand_shape">, !transform.op<"linalg.transpose">) + + // Step 5. Lower tensor.unpack + %unpack = transform.structured.match ops{["tensor.unpack"]} in %func_h + : (!transform.op<"func.func">) -> !transform.op<"tensor.unpack"> + transform.structured.lower_unpack %unpack : (!transform.op<"tensor.unpack">) + -> (!transform.op<"tensor.empty">, + !transform.op<"linalg.transpose">, + !transform.op<"tensor.collapse_shape">, + !transform.op<"tensor.extract_slice">) + transform.yield + } + + transform.named_sequence @match_mmt4d( + %entry: !transform.any_op {transform.readonly}) -> !transform.any_op { + transform.match.operation_name %entry ["linalg.mmt4d"] : !transform.any_op + transform.yield %entry : !transform.any_op + } +} + +func.func private @printMemrefI32(%ptr : tensor<*xi32>) -- GitLab From ffed554f2d6590acd5cc8d66af916ec1938326b9 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 28 Mar 2024 10:52:50 -0400 Subject: [PATCH 203/541] [libc++] Switch FreeBSD to C++26 (#86658) --- libcxx/utils/ci/buildkite-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml index 31e794e67d33..c43e41441872 100644 --- a/libcxx/utils/ci/buildkite-pipeline.yml +++ b/libcxx/utils/ci/buildkite-pipeline.yml @@ -207,7 +207,7 @@ steps: - group: ':freebsd: FreeBSD' steps: - label: FreeBSD 13 amd64 - command: libcxx/utils/ci/run-buildbot generic-cxx23 + command: libcxx/utils/ci/run-buildbot generic-cxx26 env: CC: clang17 CXX: clang++17 -- GitLab From d3aa92ed142409266ebcc9cbc20e5f2c2d0209c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= Date: Thu, 28 Mar 2024 14:53:21 +0000 Subject: [PATCH 204/541] [mlir][vector] Add support for scalable vectors to VectorLinearize (#86786) Adds support for scalable vectors to patterns defined in VectorLineralize.cpp. Linearization is disable in 2 notable cases: * vectors with more than 1 scalable dimension (we cannot represent vscale^2), * vectors initialised with arith.constant that's not a vector splat (such arith.constant Ops cannot be flattened). --- .../mlir/Dialect/Vector/Utils/VectorUtils.h | 10 +++ .../Vector/Transforms/VectorLinearize.cpp | 12 +++- mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp | 5 ++ mlir/test/Dialect/Vector/linearize.mlir | 61 ++++++++++++++++++- .../Dialect/Vector/TestVectorTransforms.cpp | 4 +- 5 files changed, 86 insertions(+), 6 deletions(-) diff --git a/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h b/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h index 2c548fb67402..f88fbdf9e627 100644 --- a/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h +++ b/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h @@ -170,6 +170,16 @@ public: PatternRewriter &rewriter) const = 0; }; +/// Returns true if the input Vector type can be linearized. +/// +/// Linearization is meant in the sense of flattening vectors, e.g.: +/// * vector -> vector +/// In this sense, Vectors that are either: +/// * already linearized, or +/// * contain more than 1 scalable dimensions, +/// are not linearizable. +bool isLinearizableVector(VectorType type); + } // namespace vector /// Constructs a permutation map of invariant memref indices to vector diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp index 38536de43f13..4fa5b8a4865b 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp @@ -49,6 +49,12 @@ struct LinearizeConstant final : OpConversionPattern { Location loc = constOp.getLoc(); auto resType = getTypeConverter()->convertType(constOp.getType()); + + if (resType.isScalable() && !isa(constOp.getValue())) + return rewriter.notifyMatchFailure( + loc, + "Cannot linearize a constant scalable vector that's not a splat"); + if (!resType) return rewriter.notifyMatchFailure(loc, "can't convert return type"); if (!isLessThanTargetBitWidth(constOp, targetVectorBitWidth)) @@ -104,11 +110,11 @@ void mlir::vector::populateVectorLinearizeTypeConversionsAndLegality( ConversionTarget &target, unsigned targetBitWidth) { typeConverter.addConversion([](VectorType type) -> std::optional { - // Ignore scalable vectors for now. - if (type.getRank() <= 1 || type.isScalable()) + if (!isLinearizableVector(type)) return type; - return VectorType::get(type.getNumElements(), type.getElementType()); + return VectorType::get(type.getNumElements(), type.getElementType(), + type.isScalable()); }); auto materializeCast = [](OpBuilder &builder, Type type, ValueRange inputs, diff --git a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp index 63ed0947cf6c..ebc6f5cbcaa9 100644 --- a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp +++ b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp @@ -317,3 +317,8 @@ SmallVector vector::getMixedSizesXfer(bool hasTensorSemantics, : memref::getMixedSizes(rewriter, loc, base); return mixedSourceDims; } + +bool vector::isLinearizableVector(VectorType type) { + auto numScalableDims = llvm::count(type.getScalableDims(), true); + return (type.getRank() > 1) && (numScalableDims <= 1); +} diff --git a/mlir/test/Dialect/Vector/linearize.mlir b/mlir/test/Dialect/Vector/linearize.mlir index 1b225c7a97d2..f0e9b3a05c06 100644 --- a/mlir/test/Dialect/Vector/linearize.mlir +++ b/mlir/test/Dialect/Vector/linearize.mlir @@ -1,5 +1,5 @@ -// RUN: mlir-opt %s -split-input-file -test-vector-linearize | FileCheck %s --check-prefixes=ALL,DEFAULT -// RUN: mlir-opt %s -split-input-file -test-vector-linearize=target-vector-bitwidth=128 | FileCheck %s --check-prefixes=ALL,BW-128 +// RUN: mlir-opt %s -split-input-file -test-vector-linearize -verify-diagnostics | FileCheck %s --check-prefixes=ALL,DEFAULT +// RUN: mlir-opt %s -split-input-file -test-vector-linearize=target-vector-bitwidth=128 -verify-diagnostics | FileCheck %s --check-prefixes=ALL,BW-128 // RUN: mlir-opt %s -split-input-file -test-vector-linearize=target-vector-bitwidth=0 | FileCheck %s --check-prefixes=ALL,BW-0 // ALL-LABEL: test_linearize @@ -97,3 +97,60 @@ func.func @test_tensor_no_linearize(%arg0: tensor<2x2xf32>, %arg1: tensor<2x2xf3 return %0, %arg0 : tensor<2x2xf32>, tensor<2x2xf32> } + +// ----- + +// ALL-LABEL: func.func @test_scalable_linearize( +// ALL-SAME: %[[ARG_0:.*]]: vector<2x[2]xf32>) -> vector<2x[2]xf32> { +func.func @test_scalable_linearize(%arg0: vector<2x[2]xf32>) -> vector<2x[2]xf32> { + // DEFAULT: %[[SC:.*]] = vector.shape_cast %[[ARG_0]] : vector<2x[2]xf32> to vector<[4]xf32> + // DEFAULT: %[[CST:.*]] = arith.constant dense<3.000000e+00> : vector<[4]xf32> + // BW-128: %[[SC:.*]] = vector.shape_cast %[[ARG_0]] : vector<2x[2]xf32> to vector<[4]xf32> + // BW-128: %[[CST:.*]] = arith.constant dense<3.000000e+00> : vector<[4]xf32> + // BW-0: %[[CST:.*]] = arith.constant dense<3.000000e+00> : vector<2x[2]xf32> + %0 = arith.constant dense<[[3., 3.], [3., 3.]]> : vector<2x[2]xf32> + + // DEFAULT: %[[SIN:.*]] = math.sin %[[SC]] : vector<[4]xf32> + // BW-128: %[[SIN:.*]] = math.sin %[[SC]] : vector<[4]xf32> + // BW-0: %[[SIN:.*]] = math.sin %[[ARG_0]] : vector<2x[2]xf32> + %1 = math.sin %arg0 : vector<2x[2]xf32> + + // DEFAULT: %[[ADDF:.*]] = arith.addf %[[SIN]], %[[CST]] : vector<[4]xf32> + // BW-128: %[[ADDF:.*]] = arith.addf %[[SIN]], %[[CST]] : vector<[4]xf32> + // BW-0: %[[RES:.*]] = arith.addf %[[CST]], %[[SIN]] : vector<2x[2]xf32> + %2 = arith.addf %0, %1 : vector<2x[2]xf32> + + // DEFAULT: %[[RES:.*]] = vector.shape_cast %[[ADDF]] : vector<[4]xf32> to vector<2x[2]xf32> + // BW-128: %[[RES:.*]] = vector.shape_cast %[[ADDF]] : vector<[4]xf32> to vector<2x[2]xf32> + // ALL: return %[[RES]] : vector<2x[2]xf32> + return %2 : vector<2x[2]xf32> +} + +// ----- + +// ALL-LABEL: func.func @test_scalable_no_linearize( +// ALL-SAME: %[[VAL_0:.*]]: vector<[2]x[2]xf32>) -> vector<[2]x[2]xf32> { +func.func @test_scalable_no_linearize(%arg0: vector<[2]x[2]xf32>) -> vector<[2]x[2]xf32> { + // ALL: %[[CST:.*]] = arith.constant dense<2.000000e+00> : vector<[2]x[2]xf32> + %0 = arith.constant dense<[[2., 2.], [2., 2.]]> : vector<[2]x[2]xf32> + + // ALL: %[[SIN:.*]] = math.sin %[[VAL_0]] : vector<[2]x[2]xf32> + %1 = math.sin %arg0 : vector<[2]x[2]xf32> + + // ALL: %[[RES:.*]] = arith.addf %[[CST]], %[[SIN]] : vector<[2]x[2]xf32> + %2 = arith.addf %0, %1 : vector<[2]x[2]xf32> + + // ALL: return %[[RES]] : vector<[2]x[2]xf32> + return %2 : vector<[2]x[2]xf32> +} + +// ----- + +func.func @test_scalable_no_linearize(%arg0: vector<2x[2]xf32>) -> vector<2x[2]xf32> { + // expected-error@+1 {{failed to legalize operation 'arith.constant' that was explicitly marked illegal}} + %0 = arith.constant dense<[[1., 1.], [3., 3.]]> : vector<2x[2]xf32> + %1 = math.sin %arg0 : vector<2x[2]xf32> + %2 = arith.addf %0, %1 : vector<2x[2]xf32> + + return %2 : vector<2x[2]xf32> +} diff --git a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp index f14fb18706d1..006225999105 100644 --- a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp +++ b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp @@ -489,7 +489,9 @@ struct TestFlattenVectorTransferPatterns Option targetVectorBitwidth{ *this, "target-vector-bitwidth", llvm::cl::desc( - "Minimum vector bitwidth to enable the flattening transformation"), + "Minimum vector bitwidth to enable the flattening transformation. " + "For scalable vectors this is the base size, i.e. the size " + "corresponding to vscale=1."), llvm::cl::init(std::numeric_limits::max())}; void runOnOperation() override { -- GitLab From ae280281ce9f14f413ced0e44158a6fd41a98243 Mon Sep 17 00:00:00 2001 From: martinboehme Date: Thu, 28 Mar 2024 16:05:11 +0100 Subject: [PATCH 205/541] [clang][dataflow] Fix for value constructor in class derived from optional. (#86942) The constructor `Derived(int)` in the newly added test `ClassDerivedFromOptionalValueConstructor` is not a template, and this used to cause an assertion failure in `valueOrConversionHasValue()` because `F.getTemplateSpecializationArgs()` returns null. (This is modeled after the `MaybeAlign(Align Value)` constructor, which similarly causes an assertion failure in the analysis when assigning an `Align` to a `MaybeAlign`.) To fix this, we can simply look at the type of the destination type which we're constructing or assigning to (instead of the function template argument), and this not only fixes this specific case but actually simplifies the implementation. I've added some additional tests for the case of assigning to a nested optional because we didn't have coverage for these and I wanted to make sure I didn't break anything. --- .../Models/UncheckedOptionalAccessModel.cpp | 45 ++++++------ .../UncheckedOptionalAccessModelTest.cpp | 69 +++++++++++++++++++ 2 files changed, 92 insertions(+), 22 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index dbf4878622eb..cadb1ceb2d85 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -512,27 +512,26 @@ void constructOptionalValue(const Expr &E, Environment &Env, /// Returns a symbolic value for the "has_value" property of an `optional` /// value that is constructed/assigned from a value of type `U` or `optional` /// where `T` is constructible from `U`. -BoolValue &valueOrConversionHasValue(const FunctionDecl &F, const Expr &E, +BoolValue &valueOrConversionHasValue(QualType DestType, const Expr &E, const MatchFinder::MatchResult &MatchRes, LatticeTransferState &State) { - assert(F.getTemplateSpecializationArgs() != nullptr); - assert(F.getTemplateSpecializationArgs()->size() > 0); - - const int TemplateParamOptionalWrappersCount = - countOptionalWrappers(*MatchRes.Context, F.getTemplateSpecializationArgs() - ->get(0) - .getAsType() - .getNonReferenceType()); + const int DestTypeOptionalWrappersCount = + countOptionalWrappers(*MatchRes.Context, DestType); const int ArgTypeOptionalWrappersCount = countOptionalWrappers( *MatchRes.Context, E.getType().getNonReferenceType()); - // Check if this is a constructor/assignment call for `optional` with - // argument of type `U` such that `T` is constructible from `U`. - if (TemplateParamOptionalWrappersCount == ArgTypeOptionalWrappersCount) + // Is this an constructor of the form `template optional(U &&)` / + // assignment of the form `template optional& operator=(U &&)` + // (where `T` is assignable / constructible from `U`)? + // We recognize this because the number of optionals in the optional being + // assigned to is different from the function argument type. + if (DestTypeOptionalWrappersCount != ArgTypeOptionalWrappersCount) return State.Env.getBoolLiteralValue(true); - // This is a constructor/assignment call for `optional` with argument of - // type `optional` such that `T` is constructible from `U`. + // Otherwise, this must be a constructor of the form + // `template optional &&)` / assignment of the form + // `template optional& operator=(optional &&) + // (where, again, `T` is assignable / constructible from `U`). auto *Loc = State.Env.get(E); if (auto *HasValueVal = getHasValue(State.Env, Loc)) return *HasValueVal; @@ -544,10 +543,11 @@ void transferValueOrConversionConstructor( LatticeTransferState &State) { assert(E->getNumArgs() > 0); - constructOptionalValue(*E, State.Env, - valueOrConversionHasValue(*E->getConstructor(), - *E->getArg(0), MatchRes, - State)); + constructOptionalValue( + *E, State.Env, + valueOrConversionHasValue( + E->getConstructor()->getThisType()->getPointeeType(), *E->getArg(0), + MatchRes, State)); } void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal, @@ -566,10 +566,11 @@ void transferValueOrConversionAssignment( const CXXOperatorCallExpr *E, const MatchFinder::MatchResult &MatchRes, LatticeTransferState &State) { assert(E->getNumArgs() > 1); - transferAssignment(E, - valueOrConversionHasValue(*E->getDirectCallee(), - *E->getArg(1), MatchRes, State), - State); + transferAssignment( + E, + valueOrConversionHasValue(E->getArg(0)->getType().getNonReferenceType(), + *E->getArg(1), MatchRes, State), + State); } void transferNulloptAssignment(const CXXOperatorCallExpr *E, diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp index 9430730004db..f16472ef1714 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp @@ -2798,6 +2798,59 @@ TEST_P(UncheckedOptionalAccessTest, OptionalValueOptional) { )"); } +TEST_P(UncheckedOptionalAccessTest, NestedOptionalAssignValue) { + ExpectDiagnosticsFor( + R"( + #include "unchecked_optional_access_test.h" + + using OptionalInt = $ns::$optional; + + void target($ns::$optional opt) { + if (!opt) return; + + // Accessing the outer optional is OK now. + *opt; + + // But accessing the nested optional is still unsafe because we haven't + // checked it. + **opt; // [[unsafe]] + + *opt = 1; + + // Accessing the nested optional is safe after assigning a value to it. + **opt; + } + )"); +} + +TEST_P(UncheckedOptionalAccessTest, NestedOptionalAssignOptional) { + ExpectDiagnosticsFor( + R"( + #include "unchecked_optional_access_test.h" + + using OptionalInt = $ns::$optional; + + void target($ns::$optional opt) { + if (!opt) return; + + // Accessing the outer optional is OK now. + *opt; + + // But accessing the nested optional is still unsafe because we haven't + // checked it. + **opt; // [[unsafe]] + + // Assign from `optional` so that we trigger conversion assignment + // instead of move assignment. + *opt = $ns::$optional(); + + // Accessing the nested optional is still unsafe after assigning an empty + // optional to it. + **opt; // [[unsafe]] + } + )"); +} + // Tests that structs can be nested. We use an optional field because its easy // to use in a test, but the type of the field shouldn't matter. TEST_P(UncheckedOptionalAccessTest, OptionalValueStruct) { @@ -3443,6 +3496,22 @@ TEST_P(UncheckedOptionalAccessTest, ClassDerivedPrivatelyFromOptional) { ast_matchers::hasName("Method")); } +TEST_P(UncheckedOptionalAccessTest, ClassDerivedFromOptionalValueConstructor) { + ExpectDiagnosticsFor(R"( + #include "unchecked_optional_access_test.h" + + struct Derived : public $ns::$optional { + Derived(int); + }; + + void target(Derived opt) { + *opt; // [[unsafe]] + opt = 1; + *opt; + } + )"); +} + // FIXME: Add support for: // - constructors (copy, move) // - assignment operators (default, copy, move) -- GitLab From e251f56a4d808340765112dd78edc6e6619dd05b Mon Sep 17 00:00:00 2001 From: Fraser Cormack Date: Thu, 28 Mar 2024 15:11:30 +0000 Subject: [PATCH 206/541] [libclc] Make CMake messages better fit into LLVM (#86945) The libclc project is currently only properly supported as an external project. However, when trying to get it to also build in-tree, the CMake configuration messages it outputs stand out amongst the rest of the LLVM projects and sub-projects. This commit makes all messages clear that they belong to the libclc project, as well as turning them into 'STATUS' messages where appropriate. --- libclc/CMakeLists.txt | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index 745b848fba49..9236f09d3667 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -45,7 +45,7 @@ option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}") include(AddLLVM) -message( "LLVM version: ${LLVM_PACKAGE_VERSION}" ) +message( STATUS "libclc LLVM version: ${LLVM_PACKAGE_VERSION}" ) if( ${LLVM_PACKAGE_VERSION} VERSION_LESS ${LIBCLC_MIN_LLVM} ) message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" ) @@ -67,14 +67,13 @@ find_program( LLVM_OPT opt PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) # Print toolchain -message( "clang: ${LLVM_CLANG}" ) -message( "llvm-as: ${LLVM_AS}" ) -message( "llvm-link: ${LLVM_LINK}" ) -message( "opt: ${LLVM_OPT}" ) -message( "llvm-spirv: ${LLVM_SPIRV}" ) -message( "" ) +message( STATUS "libclc toolchain - clang: ${LLVM_CLANG}" ) +message( STATUS "libclc toolchain - llvm-as: ${LLVM_AS}" ) +message( STATUS "libclc toolchain - llvm-link: ${LLVM_LINK}" ) +message( STATUS "libclc toolchain - opt: ${LLVM_OPT}" ) +message( STATUS "libclc toolchain - llvm-spirv: ${LLVM_SPIRV}" ) if( NOT LLVM_CLANG OR NOT LLVM_OPT OR NOT LLVM_AS OR NOT LLVM_LINK ) - message( FATAL_ERROR "toolchain incomplete!" ) + message( FATAL_ERROR "libclc toolchain incomplete!" ) endif() list( SORT LIBCLC_TARGETS_TO_BUILD ) @@ -182,7 +181,7 @@ add_custom_target( "clspv-generate_convert.cl" DEPENDS clspv-convert.cl ) enable_testing() foreach( t ${LIBCLC_TARGETS_TO_BUILD} ) - message( "BUILDING ${t}" ) + message( STATUS "libclc target '${t}' is enabled" ) string( REPLACE "-" ";" TRIPLE ${t} ) list( GET TRIPLE 0 ARCH ) list( GET TRIPLE 1 VENDOR ) @@ -265,7 +264,7 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} ) set( mcpu "-mcpu=${d}" ) set( arch_suffix "${d}-${t}" ) endif() - message( " DEVICE: ${d} ( ${${d}_aliases} )" ) + message( STATUS " device: ${d} ( ${${d}_aliases} )" ) if ( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) if( ${ARCH} STREQUAL "spirv" ) -- GitLab From 94b5c118b3da99012e00d3e2d7c74784de9fc7ab Mon Sep 17 00:00:00 2001 From: Jonas Paulsson Date: Thu, 28 Mar 2024 16:14:35 +0100 Subject: [PATCH 207/541] [ISel] Move handling of atomic loads from SystemZ to DAGCombiner (NFC). (#86484) The folding of sign/zero extensions into an atomic load by specifying an extension type is not target specific, and therefore belongs in the DAGCombiner rather than in the SystemZ backend. - Handle atomic loads similarly to regular loads by adding AtomicLoadExtActions with set/get methods. - Move SystemZ extendAtomicLoad() to DagCombiner.cpp. --- llvm/include/llvm/CodeGen/TargetLowering.h | 50 +++++++++++++++++++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 41 +++++++++++++++ llvm/lib/CodeGen/TargetLoweringBase.cpp | 6 +++ .../Target/SystemZ/SystemZISelLowering.cpp | 42 ++++------------ 4 files changed, 106 insertions(+), 33 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 59fad88f91b1..a4dc09744618 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -1454,6 +1454,28 @@ public: getLoadExtAction(ExtType, ValVT, MemVT) == Custom; } + /// Same as getLoadExtAction, but for atomic loads. + LegalizeAction getAtomicLoadExtAction(unsigned ExtType, EVT ValVT, + EVT MemVT) const { + if (ValVT.isExtended() || MemVT.isExtended()) return Expand; + unsigned ValI = (unsigned)ValVT.getSimpleVT().SimpleTy; + unsigned MemI = (unsigned)MemVT.getSimpleVT().SimpleTy; + assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::VALUETYPE_SIZE && + MemI < MVT::VALUETYPE_SIZE && "Table isn't big enough!"); + unsigned Shift = 4 * ExtType; + LegalizeAction Action = + (LegalizeAction)((AtomicLoadExtActions[ValI][MemI] >> Shift) & 0xf); + assert((Action == Legal || Action == Expand) && + "Unsupported atomic load extension action."); + return Action; + } + + /// Return true if the specified atomic load with extension is legal on + /// this target. + bool isAtomicLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const { + return getAtomicLoadExtAction(ExtType, ValVT, MemVT) == Legal; + } + /// Return how this store with truncation should be treated: either it is /// legal, needs to be promoted to a larger size, needs to be expanded to some /// other code sequence, or the target has a custom expander for it. @@ -2536,6 +2558,30 @@ protected: setLoadExtAction(ExtTypes, ValVT, MemVT, Action); } + /// Let target indicate that an extending atomic load of the specified type + /// is legal. + void setAtomicLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, + LegalizeAction Action) { + assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() && + MemVT.isValid() && "Table isn't big enough!"); + assert((unsigned)Action < 0x10 && "too many bits for bitfield array"); + unsigned Shift = 4 * ExtType; + AtomicLoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] &= + ~((uint16_t)0xF << Shift); + AtomicLoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] |= + ((uint16_t)Action << Shift); + } + void setAtomicLoadExtAction(ArrayRef ExtTypes, MVT ValVT, MVT MemVT, + LegalizeAction Action) { + for (auto ExtType : ExtTypes) + setAtomicLoadExtAction(ExtType, ValVT, MemVT, Action); + } + void setAtomicLoadExtAction(ArrayRef ExtTypes, MVT ValVT, + ArrayRef MemVTs, LegalizeAction Action) { + for (auto MemVT : MemVTs) + setAtomicLoadExtAction(ExtTypes, ValVT, MemVT, Action); + } + /// Indicate that the specified truncating store does not work with the /// specified type and indicate what to do about it. void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { @@ -3521,6 +3567,10 @@ private: /// for each of the 4 load ext types. uint16_t LoadExtActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; + /// Similar to LoadExtActions, but for atomic loads. Only Legal or Expand + /// (default) values are supported. + uint16_t AtomicLoadExtActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; + /// For each value type pair keep a LegalizeAction that indicates whether a /// truncating store of a specific value type and truncating type is legal. LegalizeAction TruncStoreActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 6dd3fbb3c97e..2f46b23a97c6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -13149,6 +13149,37 @@ tryToFoldExtOfMaskedLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, return NewLoad; } +// fold ([s|z]ext (atomic_load)) -> ([s|z]ext (truncate ([s|z]ext atomic_load))) +static SDValue tryToFoldExtOfAtomicLoad(SelectionDAG &DAG, + const TargetLowering &TLI, EVT VT, + SDValue N0, + ISD::LoadExtType ExtLoadType) { + auto *ALoad = dyn_cast(N0); + if (!ALoad || ALoad->getOpcode() != ISD::ATOMIC_LOAD) + return {}; + EVT MemoryVT = ALoad->getMemoryVT(); + if (!TLI.isAtomicLoadExtLegal(ExtLoadType, VT, MemoryVT)) + return {}; + // Can't fold into ALoad if it is already extending differently. + ISD::LoadExtType ALoadExtTy = ALoad->getExtensionType(); + if ((ALoadExtTy == ISD::ZEXTLOAD && ExtLoadType == ISD::SEXTLOAD) || + (ALoadExtTy == ISD::SEXTLOAD && ExtLoadType == ISD::ZEXTLOAD)) + return {}; + + EVT OrigVT = ALoad->getValueType(0); + assert(OrigVT.getSizeInBits() < VT.getSizeInBits() && "VT should be wider."); + auto *NewALoad = cast(DAG.getAtomic( + ISD::ATOMIC_LOAD, SDLoc(ALoad), MemoryVT, VT, ALoad->getChain(), + ALoad->getBasePtr(), ALoad->getMemOperand())); + NewALoad->setExtensionType(ExtLoadType); + DAG.ReplaceAllUsesOfValueWith( + SDValue(ALoad, 0), + DAG.getNode(ISD::TRUNCATE, SDLoc(ALoad), OrigVT, SDValue(NewALoad, 0))); + // Update the chain uses. + DAG.ReplaceAllUsesOfValueWith(SDValue(ALoad, 1), SDValue(NewALoad, 1)); + return SDValue(NewALoad, 0); +} + static SDValue foldExtendedSignBitTest(SDNode *N, SelectionDAG &DAG, bool LegalOperations) { assert((N->getOpcode() == ISD::SIGN_EXTEND || @@ -13420,6 +13451,11 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { DAG, *this, TLI, VT, LegalOperations, N, N0, ISD::SEXTLOAD)) return foldedExt; + // Try to simplify (sext (atomic_load x)). + if (SDValue foldedExt = + tryToFoldExtOfAtomicLoad(DAG, TLI, VT, N0, ISD::SEXTLOAD)) + return foldedExt; + // fold (sext (and/or/xor (load x), cst)) -> // (and/or/xor (sextload x), (sext cst)) if (ISD::isBitwiseLogicOp(N0.getOpcode()) && @@ -13731,6 +13767,11 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { if (SDValue ExtLoad = CombineExtLoad(N)) return ExtLoad; + // Try to simplify (zext (atomic_load x)). + if (SDValue foldedExt = + tryToFoldExtOfAtomicLoad(DAG, TLI, VT, N0, ISD::ZEXTLOAD)) + return foldedExt; + // fold (zext (and/or/xor (load x), cst)) -> // (and/or/xor (zextload x), (zext cst)) // Unless (and (load x) cst) will match as a zextload already and has diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index b16e78daf586..f64ded4f2cf9 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -823,6 +823,12 @@ void TargetLoweringBase::initActions() { std::fill(std::begin(TargetDAGCombineArray), std::end(TargetDAGCombineArray), 0); + // Let extending atomic loads be unsupported by default. + for (MVT ValVT : MVT::all_valuetypes()) + for (MVT MemVT : MVT::all_valuetypes()) + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, ValVT, MemVT, + Expand); + // We're somewhat special casing MVT::i2 and MVT::i4. Ideally we want to // remove this and targets should individually set these types if not legal. for (ISD::NodeType NT : enum_seq(ISD::DELETED_NODE, ISD::BUILTIN_OP_END, diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index da4bcd7f0c66..6496fe766101 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -293,6 +293,15 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::ATOMIC_LOAD, MVT::i128, Custom); setOperationAction(ISD::ATOMIC_STORE, MVT::i128, Custom); + // Mark sign/zero extending atomic loads as legal, which will make + // DAGCombiner fold extensions into atomic loads if possible. + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, MVT::i64, + {MVT::i8, MVT::i16, MVT::i32}, Legal); + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, MVT::i32, + {MVT::i8, MVT::i16}, Legal); + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, MVT::i16, + MVT::i8, Legal); + // We can use the CC result of compare-and-swap to implement // the "success" result of ATOMIC_CMP_SWAP_WITH_SUCCESS. setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i32, Custom); @@ -6614,27 +6623,6 @@ SDValue SystemZTargetLowering::combineTruncateExtract( return SDValue(); } -// Replace ALoad with a new ATOMIC_LOAD with a result that is extended to VT -// per ETy. -static SDValue extendAtomicLoad(AtomicSDNode *ALoad, EVT VT, SelectionDAG &DAG, - ISD::LoadExtType ETy) { - if (VT.getSizeInBits() > 64) - return SDValue(); - EVT OrigVT = ALoad->getValueType(0); - assert(OrigVT.getSizeInBits() < VT.getSizeInBits() && "VT should be wider."); - EVT MemoryVT = ALoad->getMemoryVT(); - auto *NewALoad = dyn_cast(DAG.getAtomic( - ISD::ATOMIC_LOAD, SDLoc(ALoad), MemoryVT, VT, ALoad->getChain(), - ALoad->getBasePtr(), ALoad->getMemOperand())); - NewALoad->setExtensionType(ETy); - DAG.ReplaceAllUsesOfValueWith( - SDValue(ALoad, 0), - DAG.getNode(ISD::TRUNCATE, SDLoc(ALoad), OrigVT, SDValue(NewALoad, 0))); - // Update the chain uses. - DAG.ReplaceAllUsesOfValueWith(SDValue(ALoad, 1), SDValue(NewALoad, 1)); - return SDValue(NewALoad, 0); -} - SDValue SystemZTargetLowering::combineZERO_EXTEND( SDNode *N, DAGCombinerInfo &DCI) const { // Convert (zext (select_ccmask C1, C2)) into (select_ccmask C1', C2') @@ -6681,12 +6669,6 @@ SDValue SystemZTargetLowering::combineZERO_EXTEND( } } - // Fold into ATOMIC_LOAD unless it is already sign extending. - if (auto *ALoad = dyn_cast(N0)) - if (ALoad->getOpcode() == ISD::ATOMIC_LOAD && - ALoad->getExtensionType() != ISD::SEXTLOAD) - return extendAtomicLoad(ALoad, VT, DAG, ISD::ZEXTLOAD); - return SDValue(); } @@ -6739,12 +6721,6 @@ SDValue SystemZTargetLowering::combineSIGN_EXTEND( } } - // Fold into ATOMIC_LOAD unless it is already zero extending. - if (auto *ALoad = dyn_cast(N0)) - if (ALoad->getOpcode() == ISD::ATOMIC_LOAD && - ALoad->getExtensionType() != ISD::ZEXTLOAD) - return extendAtomicLoad(ALoad, VT, DAG, ISD::SEXTLOAD); - return SDValue(); } -- GitLab From f566b079f171f28366a66b8afa4a975bc4005529 Mon Sep 17 00:00:00 2001 From: Jerry Wu Date: Thu, 28 Mar 2024 15:18:47 +0000 Subject: [PATCH 208/541] [MLIR] Add pattern to fold insert_slice of extract_slice (#86328) Fold the `tensor.insert_slice` of `tensor.extract_slice` into `tensor_extract_slice` when the `insert_slice` simply expand some unit dims dropped by the `extract_slice`. --- ...eConsecutiveInsertExtractSlicePatterns.cpp | 101 +++++++++++++++++- mlir/lib/Dialect/Tensor/Utils/Utils.cpp | 8 +- ...redundant-insert-slice-rank-expansion.mlir | 65 +++++++++++ 3 files changed, 168 insertions(+), 6 deletions(-) diff --git a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp index 5257310f5b00..59aa43222175 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp @@ -78,12 +78,12 @@ struct MergeConsecutiveInsertSlice : public OpRewritePattern { } }; -/// Drop redundant rank expansion. I.e., rank expansions that are directly -/// followed by rank reductions. E.g.: +/// Drop redundant rank expansion of insert_slice that are directly followed +/// by extract_slice. E.g.: /// %0 = tensor.insert_slice ... : tensor<5x10xf32> into tensor<1x1x5x10xf32> /// %1 = tensor.extract_slice %0[0, 0, 2, 3] [1, 1, 2, 2] [1, 1, 1, 1] /// : tensor<1x1x5x10xf32> to tensor<2x2xf32> -struct DropRedundantInsertSliceRankExpansion +struct DropRedundantRankExpansionOnExtractSliceOfInsertSlice : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; @@ -134,6 +134,97 @@ struct DropRedundantInsertSliceRankExpansion return success(); } }; + +/// Drop redundant rank expansion of insert_slice that direclty follows +/// extract_slice. +/// +/// This can be done when the insert_slice op purely expands ranks (adds unit +/// dims) and the extrace_slice drops corresponding unit dims. For example: +/// +/// %extracted_slice = tensor.extract_slice %in[0, 0] [1, 8] [1, 1] +/// : tensor<2x8xf32> to tensor<8xf32> +/// %inserted_slice = tensor.insert_slice %extracted_slice +/// into %dest[0, 0] [1, 8] [1, 1] +/// : tensor<8xf32> into tensor<1x8xf32> +/// +/// can be folded into: +/// +/// %extracted_slice = tensor.extract_slice %in[0, 0] [1, 8] [1, 1] +/// : tensor<2x8xf32> to tensor<1x8xf32> +struct DropRedundantRankExpansionOnInsertSliceOfExtractSlice final + : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(tensor::InsertSliceOp insertSliceOp, + PatternRewriter &rewriter) const { + auto extractSliceOp = + insertSliceOp.getSource().getDefiningOp(); + if (!extractSliceOp) { + return rewriter.notifyMatchFailure(insertSliceOp, + "source is not extract_slice"); + } + + // Can't fold if the extract_slice op has other users. + if (!extractSliceOp->hasOneUse()) { + return rewriter.notifyMatchFailure(insertSliceOp, + "source has multi-uses"); + } + + // Check if the insert_slice op purely expands ranks (add unit dims). + if (!isCastLikeInsertSliceOp(insertSliceOp)) { + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice is not cast-like"); + } + + llvm::SmallBitVector extractDroppedDims = extractSliceOp.getDroppedDims(); + llvm::SmallBitVector insertDroppedDims = insertSliceOp.getDroppedDims(); + // Can't fold if the insert_slice op expands to more dims. + if (extractDroppedDims.size() < insertDroppedDims.size()) { + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice expands more dims"); + } + + // Try to match the extract dropped dims to the insert dropped dims. This is + // done by scanning the dims of extract_slice and find the left-most one can + // match the dim of insert_slice. If a match is found, advance the dim of + // insert_slice to match the next one. + unsigned insertDimPos = 0; + for (unsigned extractDimPos = 0; extractDimPos < extractDroppedDims.size(); + ++extractDimPos) { + // Matched all dims. + if (insertDimPos == insertDroppedDims.size()) + break; + + bool isExtractDropped = extractDroppedDims[extractDimPos]; + bool isInsertDropped = insertDroppedDims[insertDimPos]; + // Match if both sides drop/keep the dim. Advance and match the next dim + // of insert_slice. + if (isExtractDropped == isInsertDropped) { + insertDimPos += 1; + } else if (!isExtractDropped && isInsertDropped) { + // Not enough extract dropped dims to match the insert dropped dims. + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice drops more unit dims"); + } + // If the dim is dropped by extract_slice and not by insert_slice, look + // the next dim of extract_slice to see if it can match the current dim of + // insert_slice. + } + // Can't match some insert dims. + if (insertDimPos != insertDroppedDims.size()) { + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice has unmatched dims"); + } + + rewriter.replaceOpWithNewOp( + insertSliceOp, insertSliceOp.getType(), extractSliceOp.getSource(), + extractSliceOp.getMixedOffsets(), extractSliceOp.getMixedSizes(), + extractSliceOp.getMixedStrides()); + rewriter.eraseOp(extractSliceOp); + + return success(); + } +}; } // namespace void mlir::tensor::populateMergeConsecutiveInsertExtractSlicePatterns( @@ -146,5 +237,7 @@ void mlir::tensor::populateMergeConsecutiveInsertExtractSlicePatterns( void mlir::tensor::populateDropRedundantInsertSliceRankExpansionPatterns( RewritePatternSet &patterns) { - patterns.add(patterns.getContext()); + patterns.add( + patterns.getContext()); } diff --git a/mlir/lib/Dialect/Tensor/Utils/Utils.cpp b/mlir/lib/Dialect/Tensor/Utils/Utils.cpp index 186f85d2ce20..2dd91e2f7a17 100644 --- a/mlir/lib/Dialect/Tensor/Utils/Utils.cpp +++ b/mlir/lib/Dialect/Tensor/Utils/Utils.cpp @@ -142,11 +142,15 @@ mlir::tensor::getUnPackInverseSrcPerm(UnPackOp unpackOp, bool mlir::tensor::isCastLikeInsertSliceOp(InsertSliceOp op) { llvm::SmallBitVector droppedDims = op.getDroppedDims(); int64_t srcDim = 0; + RankedTensorType resultType = op.getDestType(); // Source dims and destination dims (apart from dropped dims) must have the // same size. - for (int64_t resultDim = 0; resultDim < op.getDestType().getRank(); - ++resultDim) { + for (int64_t resultDim = 0; resultDim < resultType.getRank(); ++resultDim) { if (droppedDims.test(resultDim)) { + // InsertSlice may expand unit dimensions that result from inserting a + // size-1 slice into a non-size-1 result dimension. + if (resultType.getDimSize(resultDim) != 1) + return false; continue; } FailureOr equalDimSize = ValueBoundsConstraintSet::areEqual( diff --git a/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir b/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir index e337fdd93214..88e55062f477 100644 --- a/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir +++ b/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir @@ -9,3 +9,68 @@ func.func @test_drop_rank_expansion(%src: tensor<128x480xf32>, %dest: tensor<1x1 %extracted_slice = tensor.extract_slice %inserted_slice[0, 0, 0, 0] [1, 1, 123, 456] [1, 1, 1, 1] : tensor<1x1x128x480xf32> to tensor<123x456xf32> return %extracted_slice : tensor<123x456xf32> } + +// ----- + +func.func @fold_casting_insert_slice_of_extract_slice(%in : tensor, %dest : tensor<8x1x8xf32>) -> tensor<8x1x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0] [1, 8, 1, 8] [1, 1, 1, 1] : tensor to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [8, 1, 8] [1, 1, 1] : tensor<8x8xf32> into tensor<8x1x8xf32> + return %inserted_slice : tensor<8x1x8xf32> +} +// CHECK-LABEL: func.func @fold_casting_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]][0, 0, 0, 0] [1, 8, 1, 8] [1, 1, 1, 1] +// CHECK-SAME: : tensor to tensor<8x1x8xf32> +// CHECK: return %[[EXTRACTED_SLICE]] : tensor<8x1x8xf32> + +// ----- + +func.func @fold_casting_insert_slice_of_strided_extract_slice(%in : tensor, %dest : tensor<1x4x8xf32>) -> tensor<1x4x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0] [1, 4, 1, 8] [1, 2, 1, 1] : tensor to tensor<4x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [1, 4, 8] [1, 1, 1] : tensor<4x8xf32> into tensor<1x4x8xf32> + return %inserted_slice : tensor<1x4x8xf32> +} +// CHECK-LABEL: func.func @fold_casting_insert_slice_of_strided_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]][0, 0, 0, 0] [1, 4, 1, 8] [1, 2, 1, 1] +// CHECK-SAME: : tensor to tensor<1x4x8xf32> +// CHECK: return %[[EXTRACTED_SLICE]] : tensor<1x4x8xf32> + +// ----- + +func.func @no_fold_more_unit_dims_insert_slice_of_extract_slice(%in : tensor, %dest : tensor<1x1x8x8xf32>) -> tensor<1x1x8x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0] [1, 8, 8] [1, 1, 1] : tensor to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0, 0] [1, 1, 8, 8] [1, 1, 1, 1] : tensor<8x8xf32> into tensor<1x1x8x8xf32> + return %inserted_slice : tensor<1x1x8x8xf32> +} +// CHECK-LABEL: func.func @no_fold_more_unit_dims_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]] +// CHECK: %[[INSERTED_SLICE:.*]] = tensor.insert_slice %[[EXTRACTED_SLICE]] +// CHECK: return %[[INSERTED_SLICE]] : tensor<1x1x8x8xf32> + +// ----- + +func.func @no_fold_strided_insert_slice_of_extract_slice(%in : tensor, %dest : tensor<1x4x4xf32>) -> tensor<1x4x4xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0] [1, 8, 1, 8] [1, 1, 1, 1] : tensor to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [1, 8, 8] [1, 2, 2] : tensor<8x8xf32> into tensor<1x4x4xf32> + return %inserted_slice : tensor<1x4x4xf32> +} +// CHECK-LABEL: func.func @no_fold_strided_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]] +// CHECK: %[[INSERTED_SLICE:.*]] = tensor.insert_slice %[[EXTRACTED_SLICE]] +// CHECK: return %[[INSERTED_SLICE]] : tensor<1x4x4xf32> + +// ----- + +func.func @no_fold_non_casting_insert_slice_of_extract_slice(%in : tensor<1x1x1x8x8xf32>, %dest : tensor<2x8x8xf32>) -> tensor<2x8x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0, 0] [1, 1, 1, 8, 8] [1, 1, 1, 1, 1] : tensor<1x1x1x8x8xf32> to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [1, 8, 8] [1, 1, 1] : tensor<8x8xf32> into tensor<2x8x8xf32> + return %inserted_slice : tensor<2x8x8xf32> +} +// CHECK-LABEL: func.func @no_fold_non_casting_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor<1x1x1x8x8xf32> +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]] +// CHECK: %[[INSERTED_SLICE:.*]] = tensor.insert_slice %[[EXTRACTED_SLICE]] +// CHECK: return %[[INSERTED_SLICE]] : tensor<2x8x8xf32> -- GitLab From f90813543b57a9753c549ac0aac083b879b94230 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 28 Mar 2024 08:37:19 -0700 Subject: [PATCH 209/541] [MCP] Use MachineInstr::all_defs instead of MachineInstr::defs in hasOverlappingMultipleDef. (#86889) defs does not return the defs for inline assembly. We need to use all_defs to find them. Fixes #86880. --- llvm/lib/CodeGen/MachineCopyPropagation.cpp | 2 +- llvm/test/CodeGen/X86/pr86880.mir | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/pr86880.mir diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp index 9a0ab300b21b..65c067e4874b 100644 --- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp +++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp @@ -640,7 +640,7 @@ bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI, /// The umull instruction is unpredictable unless RdHi and RdLo are different. bool MachineCopyPropagation::hasOverlappingMultipleDef( const MachineInstr &MI, const MachineOperand &MODef, Register Def) { - for (const MachineOperand &MIDef : MI.defs()) { + for (const MachineOperand &MIDef : MI.all_defs()) { if ((&MIDef != &MODef) && MIDef.isReg() && TRI->regsOverlap(Def, MIDef.getReg())) return true; diff --git a/llvm/test/CodeGen/X86/pr86880.mir b/llvm/test/CodeGen/X86/pr86880.mir new file mode 100644 index 000000000000..92ebf9a265bb --- /dev/null +++ b/llvm/test/CodeGen/X86/pr86880.mir @@ -0,0 +1,21 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=x86_64-- -run-pass=machine-cp -o - %s | FileCheck %s + +--- +name: foo +tracksRegLiveness: true +body: | + bb.0: + liveins: $eax + + ; CHECK-LABEL: name: foo + ; CHECK: liveins: $eax + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def dead $eax, 2686986 /* regdef:GR32_NOREX2 */, def renamable $r15d, 10 /* regdef */, implicit-def dead $ecx, 10 /* regdef */, implicit-def dead $edx, 2147483657 /* reguse tiedto:$0 */, $eax(tied-def 3) + ; CHECK-NEXT: renamable $ecx = COPY killed renamable $r15d + ; CHECK-NEXT: NOOP implicit $ecx + INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def dead $eax, 2686986 /* regdef:GR32_NOREX2 */, def renamable $r15d, 10 /* regdef */, implicit-def dead $ecx, 10 /* regdef */, implicit-def dead $edx, 2147483657 /* reguse tiedto:$0 */, $eax(tied-def 3) + renamable $ecx = COPY killed renamable $r15d + NOOP implicit $ecx + +... -- GitLab From 152fcf6e77c9b83ac5cae1c0d7c0a9cf5680c7bd Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 28 Mar 2024 08:38:18 -0700 Subject: [PATCH 210/541] [RISCV] Add validation of SPIMM for cm.push/pop. (#84989) This checks the immediate is a multiple of 16 bytes. --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 3 ++- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 3 +++ llvm/lib/Target/RISCV/RISCVInstrInfoZc.td | 6 ++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h index c65b51218772..92f405b5f6ac 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -297,7 +297,8 @@ enum OperandType : unsigned { OPERAND_RVKRNUM_0_7, OPERAND_RVKRNUM_1_10, OPERAND_RVKRNUM_2_14, - OPERAND_LAST_RISCV_IMM = OPERAND_RVKRNUM_2_14, + OPERAND_SPIMM, + OPERAND_LAST_RISCV_IMM = OPERAND_SPIMM, // Operand is either a register or uimm5, this is used by V extension pseudo // instructions to represent a value that be passed as AVL to either vsetvli // or vsetivli. diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 14c2d41e80f1..5582de51b17d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -2050,6 +2050,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI, case RISCVOp::OPERAND_RVKRNUM_2_14: Ok = Imm >= 2 && Imm <= 14; break; + case RISCVOp::OPERAND_SPIMM: + Ok = (Imm & 0xf) == 0; + break; } if (!Ok) { ErrInfo = "Invalid immediate"; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td index a327bd3d0c28..2a4448d7881f 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td @@ -71,10 +71,11 @@ def rlist : Operand { }]; } -def stackadj : Operand { +def stackadj : RISCVOp { let ParserMatchClass = StackAdjAsmOperand; let PrintMethod = "printStackAdj"; let DecoderMethod = "decodeZcmpSpimm"; + let OperandType = "OPERAND_SPIMM"; let MCOperandPredicate = [{ int64_t Imm; if (!MCOp.evaluateAsConstantImm(Imm)) @@ -83,10 +84,11 @@ def stackadj : Operand { }]; } -def negstackadj : Operand { +def negstackadj : RISCVOp { let ParserMatchClass = NegStackAdjAsmOperand; let PrintMethod = "printNegStackAdj"; let DecoderMethod = "decodeZcmpSpimm"; + let OperandType = "OPERAND_SPIMM"; let MCOperandPredicate = [{ int64_t Imm; if (!MCOp.evaluateAsConstantImm(Imm)) -- GitLab From 7789ec067dfcb07cc1f2222f48d9bb8e004c0d72 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 28 Mar 2024 08:43:11 -0700 Subject: [PATCH 211/541] [libc] s/NULL/nullptr (#86867) Otherwise we need to pull in stddef.h for the declaration of NULL. --- libc/src/__support/char_vector.h | 8 ++++---- libc/src/stdlib/str_from_util.h | 2 +- libc/src/stdlib/strtod.cpp | 2 +- libc/src/stdlib/strtof.cpp | 2 +- libc/src/stdlib/strtold.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libc/src/__support/char_vector.h b/libc/src/__support/char_vector.h index 955abdc1fa5a..d39310e09dd7 100644 --- a/libc/src/__support/char_vector.h +++ b/libc/src/__support/char_vector.h @@ -11,8 +11,8 @@ #include "src/__support/common.h" // LIBC_INLINE -#include -#include // For allocation. +#include // size_t +#include // malloc, realloc, free namespace LIBC_NAMESPACE { @@ -46,7 +46,7 @@ public: if (cur_str == local_buffer) { char *new_str; new_str = reinterpret_cast(malloc(cur_buff_size)); - if (new_str == NULL) { + if (new_str == nullptr) { return false; } // TODO: replace with inline memcpy @@ -55,7 +55,7 @@ public: cur_str = new_str; } else { cur_str = reinterpret_cast(realloc(cur_str, cur_buff_size)); - if (cur_str == NULL) { + if (cur_str == nullptr) { return false; } } diff --git a/libc/src/stdlib/str_from_util.h b/libc/src/stdlib/str_from_util.h index c4c1c0a0ba4e..58afa98afc08 100644 --- a/libc/src/stdlib/str_from_util.h +++ b/libc/src/stdlib/str_from_util.h @@ -11,7 +11,7 @@ // %{a,A,e,E,f,F,g,G}, are not allowed and any code that does otherwise results // in undefined behaviour(including use of a '%%' conversion specifier); which // in this case is that the buffer string is simply populated with the format -// string. The case of the input being NULL should be handled in the calling +// string. The case of the input being nullptr should be handled in the calling // function (strfromf, strfromd, strfroml) itself. #ifndef LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H diff --git a/libc/src/stdlib/strtod.cpp b/libc/src/stdlib/strtod.cpp index db5e0edefb5b..461f7feb5bf6 100644 --- a/libc/src/stdlib/strtod.cpp +++ b/libc/src/stdlib/strtod.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(double, strtod, if (result.has_error()) libc_errno = result.error; - if (str_end != NULL) + if (str_end != nullptr) *str_end = const_cast(str + result.parsed_len); return result.value; diff --git a/libc/src/stdlib/strtof.cpp b/libc/src/stdlib/strtof.cpp index 2cc8829f63d3..554d096879c5 100644 --- a/libc/src/stdlib/strtof.cpp +++ b/libc/src/stdlib/strtof.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(float, strtof, if (result.has_error()) libc_errno = result.error; - if (str_end != NULL) + if (str_end != nullptr) *str_end = const_cast(str + result.parsed_len); return result.value; diff --git a/libc/src/stdlib/strtold.cpp b/libc/src/stdlib/strtold.cpp index 7378963f21b2..9c3e1db90067 100644 --- a/libc/src/stdlib/strtold.cpp +++ b/libc/src/stdlib/strtold.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(long double, strtold, if (result.has_error()) libc_errno = result.error; - if (str_end != NULL) + if (str_end != nullptr) *str_end = const_cast(str + result.parsed_len); return result.value; -- GitLab From 276335389133d6acf5f9d7d2f8ce09f9c610cb9c Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 28 Mar 2024 09:10:34 -0700 Subject: [PATCH 212/541] [Object,ELFType] Rename TargetEndianness to Endianness (#86604) `TargetEndianness` is long and unwieldy. "Target" in the name is confusing. Rename it to "Endianness". I cannot find noticeable out-of-tree users of `TargetEndianness`, but keep `TargetEndianness` to make this patch safer. `TargetEndianness` will be removed by a subsequent change. --- lld/ELF/Arch/Mips.cpp | 6 +- lld/ELF/DWARF.h | 2 +- lld/ELF/InputFiles.cpp | 6 +- lld/ELF/InputSection.cpp | 4 +- lld/ELF/SyntheticSections.cpp | 4 +- .../llvm/ExecutionEngine/Orc/ExecutionUtils.h | 2 +- llvm/include/llvm/Object/ELFObjectFile.h | 16 ++- llvm/include/llvm/Object/ELFTypes.h | 101 +++++++++--------- .../JITLink/ELFLinkGraphBuilder.h | 2 +- .../ExecutionEngine/Orc/ExecutionUtils.cpp | 4 +- llvm/lib/InterfaceStub/ELFObjHandler.cpp | 2 +- llvm/lib/ObjCopy/ELF/ELFObject.cpp | 15 ++- llvm/lib/ObjectYAML/ELFEmitter.cpp | 58 +++++----- llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h | 9 +- llvm/tools/llvm-readobj/ELFDumper.cpp | 37 +++---- 15 files changed, 130 insertions(+), 138 deletions(-) diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index b02ad10649d9..e36e9d59a740 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -380,7 +380,7 @@ bool MIPS::needsThunk(RelExpr expr, RelType type, const InputFile *file, template int64_t MIPS::getImplicitAddend(const uint8_t *buf, RelType type) const { - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; switch (type) { case R_MIPS_32: case R_MIPS_REL32: @@ -521,7 +521,7 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { // to a microMIPS target and vice versa. In that cases jump // instructions need to be replaced by their "cross-mode" // equivalents. - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; bool isMicroTgt = val & 0x1; bool isCrossJump = (isMicroTgt && isBranchReloc(type)) || (!isMicroTgt && isMicroBranchReloc(type)); @@ -567,7 +567,7 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { template void MIPS::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; RelType type = rel.type; if (ELFT::Is64Bits || config->mipsN32Abi) diff --git a/lld/ELF/DWARF.h b/lld/ELF/DWARF.h index 1b9a3e3f7794..d56895277bcc 100644 --- a/lld/ELF/DWARF.h +++ b/lld/ELF/DWARF.h @@ -74,7 +74,7 @@ public: StringRef getLineStrSection() const override { return lineStrSection; } bool isLittleEndian() const override { - return ELFT::TargetEndianness == llvm::endianness::little; + return ELFT::Endianness == llvm::endianness::little; } std::optional find(const llvm::DWARFSection &sec, diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 42761b6e1209..725c6f166fff 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -971,8 +971,8 @@ template static uint32_t readAndFeatures(const InputSection &sec) { const uint8_t *place = desc.data(); if (desc.size() < 8) reportFatal(place, "program property is too short"); - uint32_t type = read32(desc.data()); - uint32_t size = read32(desc.data() + 4); + uint32_t type = read32(desc.data()); + uint32_t size = read32(desc.data() + 4); desc = desc.slice(8); if (desc.size() < size) reportFatal(place, "program property is too short"); @@ -983,7 +983,7 @@ template static uint32_t readAndFeatures(const InputSection &sec) { // accumulate the bits set. if (size < 4) reportFatal(place, "FEATURE_1_AND entry is too short"); - featuresSet |= read32(desc.data()); + featuresSet |= read32(desc.data()); } // Padding is present in the note descriptor, if necessary. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index c34bf08757b1..4f88313b868b 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1258,10 +1258,10 @@ void EhInputSection::split(ArrayRef rels) { msg = "CIE/FDE too small"; break; } - uint64_t size = endian::read32(d.data()); + uint64_t size = endian::read32(d.data()); if (size == 0) // ZERO terminator break; - uint32_t id = endian::read32(d.data() + 4); + uint32_t id = endian::read32(d.data() + 4); size += 4; if (LLVM_UNLIKELY(size > d.size())) { // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead, diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 650bd6cd3900..8708bfeef8fa 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -415,7 +415,7 @@ void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef rels) { for (EhSectionPiece &cie : sec->cies) offsetToCie[cie.inputOff] = addCie(cie, rels); for (EhSectionPiece &fde : sec->fdes) { - uint32_t id = endian::read32(fde.data().data() + 4); + uint32_t id = endian::read32(fde.data().data() + 4); CieRecord *rec = offsetToCie[fde.inputOff + 4 - id]; if (!rec) fatal(toString(sec) + ": invalid CIE reference"); @@ -448,7 +448,7 @@ void EhFrameSection::iterateFDEWithLSDAAux( if (hasLSDA(cie)) ciesWithLSDA.insert(cie.inputOff); for (EhSectionPiece &fde : sec.fdes) { - uint32_t id = endian::read32(fde.data().data() + 4); + uint32_t id = endian::read32(fde.data().data() + 4); if (!ciesWithLSDA.contains(fde.inputOff + 4 - id)) continue; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index f7c286bec778..ed30a792e9e9 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -352,7 +352,7 @@ private: : ES(ES), L(L) {} static Expected getTargetPointerSize(const Triple &TT); - static Expected getTargetEndianness(const Triple &TT); + static Expected getEndianness(const Triple &TT); Expected> createStubsGraph(const SymbolMap &Resolved); diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index f57a7ab8882a..1d457be93741 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -419,7 +419,7 @@ protected: if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) return Error::success(); - if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness)) + if (Error E = Attributes.parse(Contents, ELFT::Endianness)) return E; break; } @@ -482,7 +482,7 @@ public: bool isDyldType() const { return isDyldELFObject; } static bool classof(const Binary *v) { return v->getType() == - getELFType(ELFT::TargetEndianness == llvm::endianness::little, + getELFType(ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits); } @@ -1155,10 +1155,9 @@ ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, ELFFile EF, const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, const Elf_Shdr *DotSymtabShndx) - : ELFObjectFileBase( - getELFType(ELFT::TargetEndianness == llvm::endianness::little, - ELFT::Is64Bits), - Object), + : ELFObjectFileBase(getELFType(ELFT::Endianness == llvm::endianness::little, + ELFT::Is64Bits), + Object), EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), DotSymtabShndxSec(DotSymtabShndx) {} @@ -1226,8 +1225,7 @@ uint8_t ELFObjectFile::getBytesInAddress() const { template StringRef ELFObjectFile::getFileFormatName() const { - constexpr bool IsLittleEndian = - ELFT::TargetEndianness == llvm::endianness::little; + constexpr bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch (EF.getHeader().e_machine) { @@ -1305,7 +1303,7 @@ StringRef ELFObjectFile::getFileFormatName() const { } template Triple::ArchType ELFObjectFile::getArch() const { - bool IsLittleEndian = ELFT::TargetEndianness == llvm::endianness::little; + bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; switch (EF.getHeader().e_machine) { case ELF::EM_68K: return Triple::m68k; diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h index 4986ecf8323d..4617b70a2f12 100644 --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -52,6 +52,7 @@ private: public: static const endianness TargetEndianness = E; + static const endianness Endianness = E; static const bool Is64Bits = Is64; using uint = std::conditional_t; @@ -145,9 +146,9 @@ using ELF64BE = ELFType; // Section header. template struct Elf_Shdr_Base; -template -struct Elf_Shdr_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -160,9 +161,9 @@ struct Elf_Shdr_Base> { Elf_Word sh_entsize; // Size of records contained within the section }; -template -struct Elf_Shdr_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -190,9 +191,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base { template struct Elf_Sym_Base; -template -struct Elf_Sym_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -201,9 +202,9 @@ struct Elf_Sym_Base> { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template -struct Elf_Sym_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -349,9 +350,9 @@ struct Elf_Vernaux_Impl { /// table section (.dynamic) look like. template struct Elf_Dyn_Base; -template -struct Elf_Dyn_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -359,9 +360,9 @@ struct Elf_Dyn_Base> { } d_un; }; -template -struct Elf_Dyn_Base> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -381,9 +382,9 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base { uintX_t getPtr() const { return d_un.d_ptr; } }; -template -struct Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply @@ -416,17 +417,17 @@ struct Elf_Rel_Impl, false> { } }; -template -struct Elf_Rel_Impl, true> - : public Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Rel_Impl, true> + : public Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) static const bool IsRela = true; Elf_Sword r_addend; // Compute value for relocatable field by adding this }; -template -struct Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply @@ -469,10 +470,10 @@ struct Elf_Rel_Impl, false> { } }; -template -struct Elf_Rel_Impl, true> - : public Elf_Rel_Impl, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Rel_Impl, true> + : public Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) static const bool IsRela = true; Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; @@ -504,9 +505,9 @@ struct Elf_Ehdr_Impl { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; -template -struct Elf_Phdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -517,9 +518,9 @@ struct Elf_Phdr_Impl> { Elf_Word p_align; // Segment alignment constraint }; -template -struct Elf_Phdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -574,17 +575,17 @@ struct Elf_GnuHash_Impl { // Compressed section headers. // http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header -template -struct Elf_Chdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Chdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word ch_type; Elf_Word ch_size; Elf_Word ch_addralign; }; -template -struct Elf_Chdr_Impl> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Chdr_Impl> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word ch_type; Elf_Word ch_reserved; Elf_Xword ch_size; @@ -742,17 +743,17 @@ template struct Elf_CGProfile_Impl { template struct Elf_Mips_RegInfo; -template -struct Elf_Mips_RegInfo> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers Elf_Addr ri_gp_value; // gp register value }; -template -struct Elf_Mips_RegInfo> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_pad; // unused padding field Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h index e1b11dfcfc21..5dae60062939 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h +++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h @@ -193,7 +193,7 @@ ELFLinkGraphBuilder::ELFLinkGraphBuilder( StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName) : ELFLinkGraphBuilderBase(std::make_unique( FileName.str(), Triple(std::move(TT)), std::move(Features), - ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::TargetEndianness), + ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::Endianness), std::move(GetEdgeKindName))), Obj(Obj) { LLVM_DEBUG( diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index 3952445bb1aa..670c8cf996fd 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -545,7 +545,7 @@ DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) { } Expected -DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) { +DLLImportDefinitionGenerator::getEndianness(const Triple &TT) { switch (TT.getArch()) { case Triple::x86_64: return llvm::endianness::little; @@ -562,7 +562,7 @@ DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { auto PointerSize = getTargetPointerSize(TT); if (!PointerSize) return PointerSize.takeError(); - auto Endianness = getTargetEndianness(TT); + auto Endianness = getEndianness(TT); if (!Endianness) return Endianness.takeError(); diff --git a/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp index c1256563d0d6..9c81a8832c0f 100644 --- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -57,7 +57,7 @@ static void initELFHeader(typename ELFT::Ehdr &ElfHeader, uint16_t Machine) { ElfHeader.e_ident[EI_MAG2] = ElfMagic[EI_MAG2]; ElfHeader.e_ident[EI_MAG3] = ElfMagic[EI_MAG3]; ElfHeader.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - bool IsLittleEndian = ELFT::TargetEndianness == llvm::endianness::little; + bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; ElfHeader.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; ElfHeader.e_ident[EI_VERSION] = EV_CURRENT; ElfHeader.e_ident[EI_OSABI] = ELFOSABI_NONE; diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp index 9547cc10d2a0..8b6a0035dae3 100644 --- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp @@ -33,6 +33,7 @@ using namespace llvm; using namespace llvm::ELF; using namespace llvm::objcopy::elf; using namespace llvm::object; +using namespace llvm::support; template void ELFWriter::writePhdr(const Segment &Seg) { uint8_t *B = reinterpret_cast(Buf->getBufferStart()) + @@ -1175,9 +1176,9 @@ template Error ELFSectionWriter::visit(const GroupSection &Sec) { ELF::Elf32_Word *Buf = reinterpret_cast(Out.getBufferStart() + Sec.Offset); - support::endian::write32(Buf++, Sec.FlagWord); + endian::write32(Buf++, Sec.FlagWord); for (SectionBase *S : Sec.GroupMembers) - support::endian::write32(Buf++, S->Index); + endian::write32(Buf++, S->Index); return Error::success(); } @@ -1522,10 +1523,9 @@ Error ELFBuilder::initGroupSection(GroupSection *GroupSec) { reinterpret_cast(GroupSec->Contents.data()); const ELF::Elf32_Word *End = Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word); - GroupSec->setFlagWord( - support::endian::read32(Word++)); + GroupSec->setFlagWord(endian::read32(Word++)); for (; Word != End; ++Word) { - uint32_t Index = support::endian::read32(Word); + uint32_t Index = support::endian::read32(Word); Expected Sec = SecTable.getSection( Index, "group member index " + Twine(Index) + " in section '" + GroupSec->Name + "' is invalid"); @@ -1993,9 +1993,8 @@ template void ELFWriter::writeEhdr() { Ehdr.e_ident[EI_MAG2] = 'L'; Ehdr.e_ident[EI_MAG3] = 'F'; Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - Ehdr.e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::endianness::big - ? ELFDATA2MSB - : ELFDATA2LSB; + Ehdr.e_ident[EI_DATA] = + ELFT::Endianness == llvm::endianness::big ? ELFDATA2MSB : ELFDATA2LSB; Ehdr.e_ident[EI_VERSION] = EV_CURRENT; Ehdr.e_ident[EI_OSABI] = Obj.OSABI; Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion; diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 58a725f8d877..b7118a543fae 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1314,7 +1314,7 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, if (!ELFT::Is64Bits && E > UINT32_MAX) reportError(Section.Name + ": the value is too large for 32-bits: 0x" + Twine::utohexstr(E)); - CBA.write(E, ELFT::TargetEndianness); + CBA.write(E, ELFT::Endianness); } SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size(); @@ -1333,7 +1333,7 @@ void ELFState::writeSectionContent( return; for (uint32_t E : *Shndx.Entries) - CBA.write(E, ELFT::TargetEndianness); + CBA.write(E, ELFT::Endianness); SHeader.sh_size = Shndx.Entries->size() * SHeader.sh_entsize; } @@ -1357,7 +1357,7 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, SectionIndex = llvm::ELF::GRP_COMDAT; else SectionIndex = toSectionIndex(Member.sectionNameOrType, Section.Name); - CBA.write(SectionIndex, ELFT::TargetEndianness); + CBA.write(SectionIndex, ELFT::Endianness); } SHeader.sh_size = SHeader.sh_entsize * Section.Members->size(); } @@ -1370,7 +1370,7 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, return; for (uint16_t Version : *Section.Entries) - CBA.write(Version, ELFT::TargetEndianness); + CBA.write(Version, ELFT::Endianness); SHeader.sh_size = Section.Entries->size() * SHeader.sh_entsize; } @@ -1382,7 +1382,7 @@ void ELFState::writeSectionContent( return; for (const ELFYAML::StackSizeEntry &E : *Section.Entries) { - CBA.write(E.Address, ELFT::TargetEndianness); + CBA.write(E.Address, ELFT::Endianness); SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(E.Size); } } @@ -1444,7 +1444,7 @@ void ELFState::writeSectionContent( uint64_t TotalNumBlocks = 0; for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) { // Write the base address of the range. - CBA.write(BBR.BaseAddress, ELFT::TargetEndianness); + CBA.write(BBR.BaseAddress, ELFT::Endianness); // Write number of BBEntries (number of basic blocks in this basic block // range). This is overridden by the 'NumBlocks' YAML field when // specified. @@ -1558,7 +1558,7 @@ void ELFState::writeSectionContent( return; for (const ELFYAML::CallGraphEntryWeight &E : *Section.Entries) { - CBA.write(E.Weight, ELFT::TargetEndianness); + CBA.write(E.Weight, ELFT::Endianness); SHeader.sh_size += sizeof(object::Elf_CGProfile_Impl); } } @@ -1572,15 +1572,15 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, CBA.write( Section.NBucket.value_or(llvm::yaml::Hex64(Section.Bucket->size())), - ELFT::TargetEndianness); + ELFT::Endianness); CBA.write( Section.NChain.value_or(llvm::yaml::Hex64(Section.Chain->size())), - ELFT::TargetEndianness); + ELFT::Endianness); for (uint32_t Val : *Section.Bucket) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); for (uint32_t Val : *Section.Chain) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); SHeader.sh_size = (2 + Section.Bucket->size() + Section.Chain->size()) * 4; } @@ -1687,8 +1687,8 @@ void ELFState::writeSectionContent( return; for (const ELFYAML::ARMIndexTableEntry &E : *Section.Entries) { - CBA.write(E.Offset, ELFT::TargetEndianness); - CBA.write(E.Value, ELFT::TargetEndianness); + CBA.write(E.Offset, ELFT::Endianness); + CBA.write(E.Value, ELFT::Endianness); } SHeader.sh_size = Section.Entries->size() * 8; } @@ -1729,8 +1729,8 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, return; for (const ELFYAML::DynamicEntry &DE : *Section.Entries) { - CBA.write(DE.Tag, ELFT::TargetEndianness); - CBA.write(DE.Val, ELFT::TargetEndianness); + CBA.write(DE.Tag, ELFT::Endianness); + CBA.write(DE.Val, ELFT::Endianness); } SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries->size(); } @@ -1758,18 +1758,18 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, for (const ELFYAML::NoteEntry &NE : *Section.Notes) { // Write name size. if (NE.Name.empty()) - CBA.write(0, ELFT::TargetEndianness); + CBA.write(0, ELFT::Endianness); else - CBA.write(NE.Name.size() + 1, ELFT::TargetEndianness); + CBA.write(NE.Name.size() + 1, ELFT::Endianness); // Write description size. if (NE.Desc.binary_size() == 0) - CBA.write(0, ELFT::TargetEndianness); + CBA.write(0, ELFT::Endianness); else - CBA.write(NE.Desc.binary_size(), ELFT::TargetEndianness); + CBA.write(NE.Desc.binary_size(), ELFT::Endianness); // Write type. - CBA.write(NE.Type, ELFT::TargetEndianness); + CBA.write(NE.Type, ELFT::Endianness); // Write name, null terminator and padding. if (!NE.Name.empty()) { @@ -1803,35 +1803,35 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, // be used to override this field, which is useful for producing broken // objects. if (Section.Header->NBuckets) - CBA.write(*Section.Header->NBuckets, ELFT::TargetEndianness); + CBA.write(*Section.Header->NBuckets, ELFT::Endianness); else - CBA.write(Section.HashBuckets->size(), ELFT::TargetEndianness); + CBA.write(Section.HashBuckets->size(), ELFT::Endianness); // Write the index of the first symbol in the dynamic symbol table accessible // via the hash table. - CBA.write(Section.Header->SymNdx, ELFT::TargetEndianness); + CBA.write(Section.Header->SymNdx, ELFT::Endianness); // Write the number of words in the Bloom filter. As above, the "MaskWords" // property can be used to set this field to any value. if (Section.Header->MaskWords) - CBA.write(*Section.Header->MaskWords, ELFT::TargetEndianness); + CBA.write(*Section.Header->MaskWords, ELFT::Endianness); else - CBA.write(Section.BloomFilter->size(), ELFT::TargetEndianness); + CBA.write(Section.BloomFilter->size(), ELFT::Endianness); // Write the shift constant used by the Bloom filter. - CBA.write(Section.Header->Shift2, ELFT::TargetEndianness); + CBA.write(Section.Header->Shift2, ELFT::Endianness); // We've finished writing the header. Now write the Bloom filter. for (llvm::yaml::Hex64 Val : *Section.BloomFilter) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); // Write an array of hash buckets. for (llvm::yaml::Hex32 Val : *Section.HashBuckets) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); // Write an array of hash values. for (llvm::yaml::Hex32 Val : *Section.HashValues) - CBA.write(Val, ELFT::TargetEndianness); + CBA.write(Val, ELFT::Endianness); SHeader.sh_size = 16 /*Header size*/ + Section.BloomFilter->size() * sizeof(typename ELFT::uint) + diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h index 2e89463e68d5..94a44e3afccb 100644 --- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h +++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h @@ -113,7 +113,7 @@ void PrinterContext::printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const { if (!Content) reportError(Content.takeError(), ObjF.getFileName()); - DataExtractor DE(*Content, ELFT::TargetEndianness == llvm::endianness::little, + DataExtractor DE(*Content, ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits ? 8 : 4); DictScope D(W, "Header"); @@ -186,10 +186,9 @@ void PrinterContext::printEHFrame(const Elf_Shdr *EHFrameShdr) const { // Construct DWARFDataExtractor to handle relocations ("PC Begin" fields). std::unique_ptr DICtx = DWARFContext::create( ObjF, DWARFContext::ProcessDebugRelocations::Process, nullptr); - DWARFDataExtractor DE(DICtx->getDWARFObj(), - DICtx->getDWARFObj().getEHFrameSection(), - ELFT::TargetEndianness == llvm::endianness::little, - ELFT::Is64Bits ? 8 : 4); + DWARFDataExtractor DE( + DICtx->getDWARFObj(), DICtx->getDWARFObj().getEHFrameSection(), + ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits ? 8 : 4); DWARFDebugFrame EHFrame(Triple::ArchType(ObjF.getArch()), /*IsEH=*/true, /*EHFrameAddress=*/Address); if (Error E = EHFrame.parse(DE)) diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index d1c05f437042..4b406ef12aec 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -74,6 +74,7 @@ using namespace llvm; using namespace llvm::object; +using namespace llvm::support; using namespace ELF; #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ @@ -3419,13 +3420,13 @@ template void ELFDumper::printStackMap() const { return; } - if (Error E = StackMapParser::validateHeader( - *ContentOrErr)) { + if (Error E = + StackMapParser::validateHeader(*ContentOrErr)) { Warn(std::move(E)); return; } - prettyPrintStackMap(W, StackMapParser(*ContentOrErr)); + prettyPrintStackMap(W, StackMapParser(*ContentOrErr)); } template @@ -5145,7 +5146,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("", DataSize); return OS.str(); } - PrData = support::endian::read32(Data.data()); + PrData = endian::read32(Data.data()); if (PrData == 0) { OS << ""; return OS.str(); @@ -5169,7 +5170,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("", DataSize); return OS.str(); } - PrData = support::endian::read32(Data.data()); + PrData = endian::read32(Data.data()); if (PrData == 0) { OS << ""; return OS.str(); @@ -5195,7 +5196,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("", DataSize); return OS.str(); } - PrData = support::endian::read32(Data.data()); + PrData = endian::read32(Data.data()); if (PrData == 0) { OS << ""; return OS.str(); @@ -5374,10 +5375,8 @@ static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType, return false; } - uint64_t Platform = - support::endian::read64(Desc.data() + 0); - uint64_t Version = - support::endian::read64(Desc.data() + 8); + uint64_t Platform = endian::read64(Desc.data() + 0); + uint64_t Version = endian::read64(Desc.data() + 8); OS << format("platform 0x%" PRIx64 ", version 0x%" PRIx64, Platform, Version); if (Desc.size() > 16) @@ -5457,16 +5456,14 @@ getFreeBSDNote(uint32_t NoteType, ArrayRef Desc, bool IsCore) { case ELF::NT_FREEBSD_ABI_TAG: if (Desc.size() != 4) return std::nullopt; - return FreeBSDNote{ - "ABI tag", - utostr(support::endian::read32(Desc.data()))}; + return FreeBSDNote{"ABI tag", + utostr(endian::read32(Desc.data()))}; case ELF::NT_FREEBSD_ARCH_TAG: return FreeBSDNote{"Arch tag", toStringRef(Desc).str()}; case ELF::NT_FREEBSD_FEATURE_CTL: { if (Desc.size() != 4) return std::nullopt; - unsigned Value = - support::endian::read32(Desc.data()); + unsigned Value = endian::read32(Desc.data()); std::string FlagsStr; raw_string_ostream OS(FlagsStr); printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS); @@ -6053,7 +6050,7 @@ template void GNUELFDumper::printNotes() { } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor( - Descriptor, ELFT::TargetEndianness == llvm::endianness::little, + Descriptor, ELFT::Endianness == llvm::endianness::little, sizeof(Elf_Addr)); if (Expected NoteOrErr = readCoreNote(DescExtractor)) { printCoreNote(OS, *NoteOrErr); @@ -7714,10 +7711,8 @@ static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, if (Desc.size() < 16) return false; - uint64_t platform = - support::endian::read64(Desc.data() + 0); - uint64_t version = - support::endian::read64(Desc.data() + 8); + uint64_t platform = endian::read64(Desc.data() + 0); + uint64_t version = endian::read64(Desc.data() + 8); W.printNumber("Platform", platform); W.printNumber("Version", version); @@ -7852,7 +7847,7 @@ template void LLVMELFDumper::printNotes() { } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor( - Descriptor, ELFT::TargetEndianness == llvm::endianness::little, + Descriptor, ELFT::Endianness == llvm::endianness::little, sizeof(Elf_Addr)); if (Expected N = readCoreNote(DescExtractor)) { printCoreNoteLLVMStyle(*N, W); -- GitLab From 0f61051f541a5b8cfce25c84262dfdbadb9ca688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Thu, 28 Mar 2024 17:18:05 +0100 Subject: [PATCH 213/541] [clang][HLSL][SPRI-V] Add convergence intrinsics (#80680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HLSL has wave operations and other kind of function which required the control flow to either be converged, or respect certain constraints as where and how to re-converge. At the HLSL level, the convergence are mostly obvious: the control flow is expected to re-converge at the end of a scope. Once translated to IR, HLSL scopes disapear. This means we need a way to communicate convergence restrictions down to the backend. For this, the SPIR-V backend uses convergence intrinsics. So this commit adds some code to generate convergence intrinsics when required. --------- Signed-off-by: Nathan Gauër --- clang/include/clang/Basic/Builtins.td | 6 ++ clang/lib/CodeGen/CGBuiltin.cpp | 93 +++++++++++++++++++ clang/lib/CodeGen/CGCall.cpp | 3 + clang/lib/CodeGen/CGLoopInfo.h | 7 +- clang/lib/CodeGen/CodeGenFunction.h | 19 ++++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 7 +- .../wave_get_lane_index_do_while.hlsl | 40 ++++++++ .../builtins/wave_get_lane_index_simple.hlsl | 14 +++ .../builtins/wave_get_lane_index_subcall.hlsl | 21 +++++ llvm/include/llvm/IR/IntrinsicInst.h | 13 +++ 10 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl create mode 100644 clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl create mode 100644 clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 52c0dd52c28b..f421223ff087 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4599,6 +4599,12 @@ def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> { let Prototype = "unsigned int(bool)"; } +def HLSLWaveGetLaneIndex : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_wave_get_lane_index"]; + let Attributes = [NoThrow, Const]; + let Prototype = "unsigned int()"; +} + def HLSLClamp : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_clamp"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 5ab5917c0c8d..287e763bad82 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1131,8 +1131,92 @@ struct BitTest { static BitTest decodeBitTestBuiltin(unsigned BuiltinID); }; + +// Returns the first convergence entry/loop/anchor instruction found in |BB|. +// std::nullptr otherwise. +llvm::IntrinsicInst *getConvergenceToken(llvm::BasicBlock *BB) { + for (auto &I : *BB) { + auto *II = dyn_cast(&I); + if (II && isConvergenceControlIntrinsic(II->getIntrinsicID())) + return II; + } + return nullptr; +} + } // namespace +llvm::CallBase * +CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input, + llvm::Value *ParentToken) { + llvm::Value *bundleArgs[] = {ParentToken}; + llvm::OperandBundleDef OB("convergencectrl", bundleArgs); + auto Output = llvm::CallBase::addOperandBundle( + Input, llvm::LLVMContext::OB_convergencectrl, OB, Input); + Input->replaceAllUsesWith(Output); + Input->eraseFromParent(); + return Output; +} + +llvm::IntrinsicInst * +CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB, + llvm::Value *ParentToken) { + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(&BB->front()); + auto CB = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_loop, {}, {}); + Builder.restoreIP(IP); + + auto I = addConvergenceControlToken(CB, ParentToken); + return cast(I); +} + +llvm::IntrinsicInst * +CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) { + auto *BB = &F->getEntryBlock(); + auto *token = getConvergenceToken(BB); + if (token) + return token; + + // Adding a convergence token requires the function to be marked as + // convergent. + F->setConvergent(); + + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(&BB->front()); + auto I = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_entry, {}, {}); + assert(isa(I)); + Builder.restoreIP(IP); + + return cast(I); +} + +llvm::IntrinsicInst * +CodeGenFunction::getOrEmitConvergenceLoopToken(const LoopInfo *LI) { + assert(LI != nullptr); + + auto *token = getConvergenceToken(LI->getHeader()); + if (token) + return token; + + llvm::IntrinsicInst *PII = + LI->getParent() + ? emitConvergenceLoopToken( + LI->getHeader(), getOrEmitConvergenceLoopToken(LI->getParent())) + : getOrEmitConvergenceEntryToken(LI->getHeader()->getParent()); + + return emitConvergenceLoopToken(LI->getHeader(), PII); +} + +llvm::CallBase * +CodeGenFunction::addControlledConvergenceToken(llvm::CallBase *Input) { + llvm::Value *ParentToken = + LoopStack.hasInfo() + ? getOrEmitConvergenceLoopToken(&LoopStack.getInfo()) + : getOrEmitConvergenceEntryToken(Input->getFunction()); + return addConvergenceControlToken(Input, ParentToken); +} + BitTest BitTest::decodeBitTestBuiltin(unsigned BuiltinID) { switch (BuiltinID) { // Main portable variants. @@ -5809,6 +5893,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, {NDRange, Kernel, Block})); } + case Builtin::BI__builtin_hlsl_wave_get_lane_index: { + auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction( + llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", + {}, false, true)); + if (getTarget().getTriple().isSPIRVLogical()) + CI = dyn_cast(addControlledConvergenceToken(CI)); + return RValue::get(CI); + } + case Builtin::BI__builtin_store_half: case Builtin::BI__builtin_store_halff: { Value *Val = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index fb0078214b07..a5fe39633679 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5715,6 +5715,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (!CI->getType()->isVoidTy()) CI->setName("call"); + if (getTarget().getTriple().isSPIRVLogical() && CI->isConvergent()) + CI = addControlledConvergenceToken(CI); + // Update largest vector width from the return type. LargestVectorWidth = std::max(LargestVectorWidth, getMaxVectorWidth(CI->getType())); diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h index a1c8c7e5307f..0fe33b289130 100644 --- a/clang/lib/CodeGen/CGLoopInfo.h +++ b/clang/lib/CodeGen/CGLoopInfo.h @@ -110,6 +110,10 @@ public: /// been processed. void finish(); + /// Returns the first outer loop containing this loop if any, nullptr + /// otherwise. + const LoopInfo *getParent() const { return Parent; } + private: /// Loop ID metadata. llvm::TempMDTuple TempLoopID; @@ -291,12 +295,13 @@ public: /// Set no progress for the next loop pushed. void setMustProgress(bool P) { StagedAttrs.MustProgress = P; } -private: /// Returns true if there is LoopInfo on the stack. bool hasInfo() const { return !Active.empty(); } /// Return the LoopInfo for the current loop. HasInfo should be called /// first to ensure LoopInfo is present. const LoopInfo &getInfo() const { return *Active.back(); } + +private: /// The set of attributes that will be applied to the next pushed loop. LoopAttributes StagedAttrs; /// Stack of active loops. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8dd6da5f85f1..e2a7e28c8211 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4985,6 +4985,25 @@ public: llvm::Value *emitBoolVecConversion(llvm::Value *SrcVec, unsigned NumElementsDst, const llvm::Twine &Name = ""); + // Adds a convergence_ctrl token to |Input| and emits the required parent + // convergence instructions. + llvm::CallBase *addControlledConvergenceToken(llvm::CallBase *Input); + +private: + // Emits a convergence_loop instruction for the given |BB|, with |ParentToken| + // as it's parent convergence instr. + llvm::IntrinsicInst *emitConvergenceLoopToken(llvm::BasicBlock *BB, + llvm::Value *ParentToken); + // Adds a convergence_ctrl token with |ParentToken| as parent convergence + // instr to the call |Input|. + llvm::CallBase *addConvergenceControlToken(llvm::CallBase *Input, + llvm::Value *ParentToken); + // Find the convergence_entry instruction |F|, or emits ones if none exists. + // Returns the convergence instruction. + llvm::IntrinsicInst *getOrEmitConvergenceEntryToken(llvm::Function *F); + // Find the convergence_loop instruction for the loop defined by |LI|, or + // emits one if none exists. Returns the convergence instruction. + llvm::IntrinsicInst *getOrEmitConvergenceLoopToken(const LoopInfo *LI); private: llvm::MDNode *getRangeForLoadFromType(QualType Ty); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d47eab453f87..ecf20f6f1136 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1389,7 +1389,12 @@ float4 trunc(float4); /// true, across all active lanes in the current wave. _HLSL_AVAILABILITY(shadermodel, 6.0) _HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_count_bits) -uint WaveActiveCountBits(bool Val); +__attribute__((convergent)) uint WaveActiveCountBits(bool Val); + +/// \brief Returns the index of the current lane within the current wave. +_HLSL_AVAILABILITY(shadermodel, 6.0) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_get_lane_index) +__attribute__((convergent)) uint WaveGetLaneIndex(); } // namespace hlsl #endif //_HLSL_HLSL_INTRINSICS_H_ diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl new file mode 100644 index 000000000000..9481b0d60a27 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func void @main() [[A0:#[0-9]+]] { +void main() { +// CHECK: entry: +// CHECK: %[[CT_ENTRY:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: br label %[[LABEL_WHILE_COND:.+]] + int cond = 0; + +// CHECK: [[LABEL_WHILE_COND]]: +// CHECK: %[[CT_LOOP:[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %[[CT_ENTRY]]) ] +// CHECK: br label %[[LABEL_WHILE_BODY:.+]] + while (true) { + +// CHECK: [[LABEL_WHILE_BODY]]: +// CHECK: br i1 {{%.+}}, label %[[LABEL_IF_THEN:.+]], label %[[LABEL_IF_END:.+]] + +// CHECK: [[LABEL_IF_THEN]]: +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CT_LOOP]]) ] +// CHECK: br label %[[LABEL_WHILE_END:.+]] + if (cond == 2) { + uint index = WaveGetLaneIndex(); + break; + } + +// CHECK: [[LABEL_IF_END]]: +// CHECK: br label %[[LABEL_WHILE_COND]] + cond++; + } + +// CHECK: [[LABEL_WHILE_END]]: +// CHECK: ret void +} + +// CHECK-DAG: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK-DAG: attributes [[A0]] = {{{.*}}convergent{{.*}}} +// CHECK-DAG: attributes [[A1]] = {{{.*}}convergent{{.*}}} + diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl new file mode 100644 index 000000000000..8f52d81091c1 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] { +// CHECK: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ] +uint test_1() { + return WaveGetLaneIndex(); +} + +// CHECK: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } +// CHECK-DAG: attributes [[A1]] = { {{.*}}convergent{{.*}} } diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl new file mode 100644 index 000000000000..379c8f118f52 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] { +// CHECK: %[[C1:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[C1]]) ] +uint test_1() { + return WaveGetLaneIndex(); +} + +// CHECK-DAG: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK: define spir_func noundef i32 @_Z6test_2v() [[A0]] { +// CHECK: %[[C2:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i32 @_Z6test_1v() [ "convergencectrl"(token %[[C2]]) ] +uint test_2() { + return test_1(); +} + +// CHECK-DAG: attributes [[A0]] = {{{.*}}convergent{{.*}}} +// CHECK-DAG: attributes [[A1]] = {{{.*}}convergent{{.*}}} diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h index c07b83a81a63..4f22720f1c55 100644 --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -1782,6 +1782,19 @@ public: static bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + + // Returns the convergence intrinsic referenced by |I|'s convergencectrl + // attribute if any. + static IntrinsicInst *getParentConvergenceToken(Instruction *I) { + auto *CI = dyn_cast(I); + if (!CI) + return nullptr; + + auto Bundle = CI->getOperandBundle(llvm::LLVMContext::OB_convergencectrl); + assert(Bundle->Inputs.size() == 1 && + Bundle->Inputs[0]->getType()->isTokenTy()); + return dyn_cast(Bundle->Inputs[0].get()); + } }; } // end namespace llvm -- GitLab From 36b86438d7cd652bcac3fce51c1bdfad99536ec8 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <1802579+farzonl@users.noreply.github.com> Date: Thu, 28 Mar 2024 12:32:28 -0400 Subject: [PATCH 214/541] [DXIL] Implement pow lowering (#86733) closes #86179 - `DXILIntrinsicExpansion.cpp` - add the pow expansion to exp2(y*log2(x)) --- .../Target/DirectX/DXILIntrinsicExpansion.cpp | 23 +++++++++++++++ llvm/test/CodeGen/DirectX/pow-vec.ll | 15 ++++++++++ llvm/test/CodeGen/DirectX/pow.ll | 29 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/pow-vec.ll create mode 100644 llvm/test/CodeGen/DirectX/pow.ll diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp index 3cc375edabde..3e2d10f5ee7a 100644 --- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -37,6 +37,7 @@ static bool isIntrinsicExpansion(Function &F) { case Intrinsic::exp: case Intrinsic::log: case Intrinsic::log10: + case Intrinsic::pow: case Intrinsic::dx_any: case Intrinsic::dx_clamp: case Intrinsic::dx_uclamp: @@ -197,6 +198,26 @@ static bool expandLog10Intrinsic(CallInst *Orig) { return expandLogIntrinsic(Orig, numbers::ln2f / numbers::ln10f); } +static bool expandPowIntrinsic(CallInst *Orig) { + + Value *X = Orig->getOperand(0); + Value *Y = Orig->getOperand(1); + Type *Ty = X->getType(); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + + auto *Log2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2"); + auto *Mul = Builder.CreateFMul(Log2Call, Y); + auto *Exp2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2"); + Exp2Call->setTailCall(Orig->isTailCall()); + Exp2Call->setAttributes(Orig->getAttributes()); + Orig->replaceAllUsesWith(Exp2Call); + Orig->eraseFromParent(); + return true; +} + static bool expandRcpIntrinsic(CallInst *Orig) { Value *X = Orig->getOperand(0); IRBuilder<> Builder(Orig->getParent()); @@ -270,6 +291,8 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) { return expandLogIntrinsic(Orig); case Intrinsic::log10: return expandLog10Intrinsic(Orig); + case Intrinsic::pow: + return expandPowIntrinsic(Orig); case Intrinsic::dx_any: return expandAnyIntrinsic(Orig); case Intrinsic::dx_uclamp: diff --git a/llvm/test/CodeGen/DirectX/pow-vec.ll b/llvm/test/CodeGen/DirectX/pow-vec.ll new file mode 100644 index 000000000000..781fa5b8cb24 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pow-vec.ll @@ -0,0 +1,15 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s + +; Make sure dxil operation function calls for pow are generated for float and half. + +; CHECK-LABEL: pow_float4 +; CHECK: call <4 x float> @llvm.log2.v4f32(<4 x float> %a) +; CHECK: fmul <4 x float> %{{.*}}, %b +; CHECK: call <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}}) +define noundef <4 x float> @pow_float4(<4 x float> noundef %a, <4 x float> noundef %b) { +entry: + %elt.pow = call <4 x float> @llvm.pow.v4f32(<4 x float> %a, <4 x float> %b) + ret <4 x float> %elt.pow +} + +declare <4 x float> @llvm.pow.v4f32(<4 x float>,<4 x float>) diff --git a/llvm/test/CodeGen/DirectX/pow.ll b/llvm/test/CodeGen/DirectX/pow.ll new file mode 100644 index 000000000000..25ce0fe731d0 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pow.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK + +; Make sure dxil operation function calls for pow are generated. + +define noundef float @pow_float(float noundef %a, float noundef %b) { +entry: +; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %a) +; EXPCHECK: call float @llvm.log2.f32(float %a) +; CHECK: fmul float %{{.*}}, %b +; DOPCHECK: call float @dx.op.unary.f32(i32 21, float %{{.*}}) +; EXPCHECK: call float @llvm.exp2.f32(float %{{.*}}) + %elt.pow = call float @llvm.pow.f32(float %a, float %b) + ret float %elt.pow +} + +define noundef half @pow_half(half noundef %a, half noundef %b) { +entry: +; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %a) +; EXPCHECK: call half @llvm.log2.f16(half %a) +; CHECK: fmul half %{{.*}}, %b +; DOPCHECK: call half @dx.op.unary.f16(i32 21, half %{{.*}}) +; EXPCHECK: call half @llvm.exp2.f16(half %{{.*}}) + %elt.pow = call half @llvm.pow.f16(half %a, half %b) + ret half %elt.pow +} + +declare half @llvm.pow.f16(half,half) +declare float @llvm.pow.f32(float,float) -- GitLab From 39fe729502006f1b108828b75af8d63a27364f80 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Thu, 28 Mar 2024 09:41:08 -0700 Subject: [PATCH 215/541] [lld-macho] Ignore -no_warn_duplicate_libraries flag (#86303) This is a new ld64 flag (along with `-warn_duplicate_libraries`), where the warning is enabled by default, and it can be useful to ignore since it can be hard to dedup library flags across large builds. This doesn't ignore the enabling version since if someone manually passed that and lld didn't respect it, we probably want the user to know that. --- lld/MachO/Options.td | 6 ++++++ lld/test/MachO/silent-ignore.s | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td index 19f8509ba714..11458d92b3ab 100644 --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -1413,3 +1413,9 @@ def debug_variant : Flag<["-"], "debug_variant">, HelpText<"Do not warn about issues that are only problems for binaries shipping to customers.">, Flags<[HelpHidden]>, Group; + +// NOTE: This flag should be respected if -warn_duplicate_libraries is ever implemented. +def no_warn_duplicate_libraries : Flag<["-"], "no_warn_duplicate_libraries">, + HelpText<"Do not warn if the input contains duplicate library options.">, + Flags<[HelpHidden]>, + Group; diff --git a/lld/test/MachO/silent-ignore.s b/lld/test/MachO/silent-ignore.s index e57342c28a7a..58c3cc148f07 100644 --- a/lld/test/MachO/silent-ignore.s +++ b/lld/test/MachO/silent-ignore.s @@ -20,7 +20,7 @@ ## Check that we don't emit any warnings nor errors for these unimplemented flags. # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o -# RUN: %lld %t.o -o /dev/null -objc_abi_version 2 -debug_variant +# RUN: %lld %t.o -o /dev/null -objc_abi_version 2 -debug_variant -no_warn_duplicate_libraries .globl _main _main: -- GitLab From 706c1302f99d79af21ddf22e23c53d33329f225a Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Thu, 28 Mar 2024 09:43:03 -0700 Subject: [PATCH 216/541] [Dialect] Fix a warning This patch fixes: mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp:158:17: error: 'matchAndRewrite' overrides a member function but is not marked 'override' [-Werror,-Wsuggest-override] --- .../Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp index 59aa43222175..ff003e486d21 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp @@ -156,7 +156,7 @@ struct DropRedundantRankExpansionOnInsertSliceOfExtractSlice final using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(tensor::InsertSliceOp insertSliceOp, - PatternRewriter &rewriter) const { + PatternRewriter &rewriter) const override { auto extractSliceOp = insertSliceOp.getSource().getDefiningOp(); if (!extractSliceOp) { -- GitLab From 423832421b9b259612c3fe4169a6a6e1e2600f95 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Thu, 28 Mar 2024 09:52:25 -0700 Subject: [PATCH 217/541] [asan][windows] Weak function interception support in instruction size decoder. (#86570) This makes it so we'll be able to decode the instructions used in the weak function stubs from https://github.com/llvm/llvm-project/pull/81677. This code doesn't technically require those changes. Co-authored-by: Amy Wishnousky --- compiler-rt/lib/interception/interception_win.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index a04175ba1e4b..a638e66eccee 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -479,6 +479,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { switch (*(u8*)address) { case 0x90: // 90 : nop + case 0xC3: // C3 : ret (for small/empty function interception + case 0xCC: // CC : int 3 i.e. registering weak functions) return 1; case 0x50: // push eax / rax @@ -502,7 +504,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { // Cannot overwrite control-instruction. Return 0 to indicate failure. case 0xE9: // E9 XX XX XX XX : jmp